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 2911 - (hide annotations) (download) (as text)
Fri Oct 6 16:35:25 2006 UTC (17 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 90816 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 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     // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1287     } else if (MATCH_STR(option + 1, "1") == 0) {
1288     // command line: /ssh /1 is SSH1 only
1289     pvar->settings.ssh_protocol_version = 1;
1290    
1291     } else if (MATCH_STR(option + 1, "2") == 0) {
1292     // command line: /ssh /2 is SSH2 & SSH1
1293     pvar->settings.ssh_protocol_version = 2;
1294    
1295     } else if (MATCH_STR(option + 1, "nossh") == 0) {
1296     // '/nossh' �I�v�V�����������B
1297     // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1298     // �����������������B(2004.10.11 yutaka)
1299     pvar->settings.Enabled = 0;
1300    
1301 maya 2907 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1302     // '/telnet' ���w�������������������� '/nossh' ��������
1303     // SSH������������ (2006.9.16 maya)
1304     pvar->settings.Enabled = 0;
1305    
1306 yutakakn 2739 } else if (MATCH_STR(option + 1, "auth") == 0) {
1307 yutakakn 2784 // SSH2�������O�C���I�v�V����������
1308 yutakakn 2739 //
1309 yutakakn 2784 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1310     // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1311     // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1312     // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1313     // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1314 yutakakn 2739 //
1315 yutakakn 2784 // (2004.11.30 yutaka)
1316     // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1317     //
1318 yutakakn 2739 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1319    
1320 yutakakn 2784 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h/keyboard-interactive�F��
1321     //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1322     pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1323 yutakakn 2739
1324 yutakakn 2784 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1325     //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1326     pvar->ssh2_authmethod = SSH_AUTH_RSA;
1327    
1328 yutakakn 2739 } else {
1329     // TODO:
1330    
1331     }
1332    
1333     } else if (MATCH_STR(option + 1, "user=") == 0) {
1334 yutakakn 2784 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1335     //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1336 yutakakn 2739
1337     } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1338 yutakakn 2784 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1339     //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1340 yutakakn 2739
1341 yutakakn 2784 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1342     replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1343    
1344 maya 2908 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1345     // �p�X���[�h������ (2006.9.18 maya)
1346     pvar->ask4passwd = 1;
1347    
1348 yutakakn 2728 }
1349    
1350 maya 2908 // �p�X���[�h�������������������O�C��������������
1351     // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1352     if (pvar->ask4passwd == 1) {
1353     pvar->ssh2_autologin = 0;
1354     }
1355    
1356 yutakakn 2728 }
1357    
1358     return 0;
1359     }
1360    
1361     static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1362     PCHAR DDETopic)
1363     {
1364 maya 2911 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1365 yutakakn 2728 int i;
1366     BOOL inParam = FALSE;
1367     BOOL inQuotes = FALSE;
1368 maya 2911 BOOL inFileParam = FALSE;
1369 yutakakn 2728 PCHAR option = NULL;
1370     GET_VAR();
1371    
1372     if (pvar->hostdlg_activated) {
1373     pvar->settings.Enabled = pvar->hostdlg_Enabled;
1374     }
1375    
1376     for (i = 0; param[i] != 0; i++) {
1377 maya 2911 if (inQuotes ? param[i] == '"'
1378     : (param[i] == ' ' || param[i] == '\t')) {
1379 yutakakn 2728 if (option != NULL) {
1380     char ch = param[i];
1381 maya 2911 PCHAR Equal;
1382 yutakakn 2728
1383     param[i] = 0;
1384 maya 2911 Equal = strchr(option, '=');
1385     if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1386     char *buf = (char *)calloc(strlen(option), sizeof(char));
1387     strncat(buf, option, Equal - option + 1);
1388     strcat(buf, Equal + 2);
1389     if (parse_option
1390     (pvar, *buf == '"' ? buf + 1 : buf)) {
1391     memset(option, ' ', i + 1 - (option - param));
1392     } else {
1393     param[i] = ch;
1394     }
1395     free(buf);
1396 yutakakn 2728 }
1397 maya 2911 else {
1398     if (parse_option
1399     (pvar, *option == '"' ? option + 1 : option)) {
1400     memset(option, ' ', i + 1 - (option - param));
1401     } else {
1402     param[i] = ch;
1403     }
1404     }
1405 yutakakn 2728 option = NULL;
1406     }
1407     inParam = FALSE;
1408     inQuotes = FALSE;
1409 maya 2911 inFileParam = FALSE;
1410 yutakakn 2728 } else if (!inParam) {
1411     if (param[i] == '"') {
1412     inQuotes = TRUE;
1413     inParam = TRUE;
1414     option = param + i;
1415     } else if (param[i] != ' ' && param[i] != '\t') {
1416     inParam = TRUE;
1417     option = param + i;
1418     }
1419 maya 2911 } else {
1420     if (option == NULL) {
1421     continue;
1422     }
1423     if ((option[0] == '-' || option[0] == '/') &&
1424     (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1425     MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1426     MATCH_STR(option + 1, "f=") == 0)) {
1427     if (param[i] == '"') {
1428     inQuotes = TRUE;
1429     }
1430     inFileParam = TRUE;
1431     }
1432 yutakakn 2728 }
1433     }
1434    
1435     if (option != NULL) {
1436 maya 2911 PCHAR Equal = strchr(option, '=');
1437     if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1438     char *buf = (char *)calloc(strlen(option), sizeof(char));
1439     strncat(buf, option, Equal - option + 1);
1440     strcat(buf, Equal + 2);
1441     if (parse_option
1442     (pvar, *buf == '"' ? buf + 1 : buf)) {
1443     memset(option, ' ', i + 1 - (option - param));
1444     }
1445     free(buf);
1446 yutakakn 2728 }
1447 maya 2911 else {
1448     if (parse_option(pvar, option)) {
1449     memset(option, ' ', i - (option - param));
1450     }
1451     }
1452 yutakakn 2728 }
1453    
1454     FWDUI_load_settings(pvar);
1455    
1456     (pvar->ParseParam) (param, ts, DDETopic);
1457    
1458     }
1459    
1460     static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1461     {
1462     GET_VAR();
1463    
1464     pvar->ReadIniFile = *hooks->ReadIniFile;
1465     pvar->WriteIniFile = *hooks->WriteIniFile;
1466     pvar->ParseParam = *hooks->ParseParam;
1467    
1468     *hooks->ReadIniFile = TTXReadINIFile;
1469     *hooks->WriteIniFile = TTXWriteINIFile;
1470     *hooks->ParseParam = TTXParseParam;
1471     }
1472    
1473     static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1474     {
1475     GET_VAR();
1476    
1477     SSH_notify_win_size(pvar, cols, rows);
1478     }
1479    
1480     static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1481     WORD newItemID, char FAR * text)
1482     {
1483     int i, j;
1484    
1485     for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1486     HMENU submenu = GetSubMenu(menu, i);
1487    
1488     for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1489     if (GetMenuItemID(submenu, j) == beforeItemID) {
1490     InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1491     text);
1492     return;
1493     }
1494     }
1495     }
1496     }
1497    
1498     static void PASCAL FAR TTXModifyMenu(HMENU menu)
1499     {
1500     GET_VAR();
1501    
1502     /* inserts before ID_HELP_ABOUT */
1503     insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1504     "About &TTSSH...");
1505    
1506     /* inserts before ID_SETUP_TCPIP */
1507     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1508     "SS&H...");
1509     /* inserts before ID_SETUP_TCPIP */
1510     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1511     "SSH &Authentication...");
1512     /* inserts before ID_SETUP_TCPIP */
1513     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1514     "SSH F&orwarding...");
1515 yutakakn 2816
1516     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU,
1517     "SSH KeyGenerator...");
1518 yutakakn 2728 }
1519    
1520     static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1521     {
1522     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1523     (LPARAM) prefix);
1524     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1525     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1526     (LPARAM) (char FAR *) "\r\n");
1527     }
1528    
1529 yutakakn 2792 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1530 yutakakn 2793 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1531 yutakakn 2792 {
1532     typedef struct {
1533     WORD wLanguage;
1534     WORD wCodePage;
1535     } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1536     LPLANGANDCODEPAGE lplgcode;
1537     UINT unLen;
1538     DWORD size;
1539     char *buf = NULL;
1540     BOOL ret;
1541     int i;
1542     char fmt[80];
1543     char *pbuf;
1544    
1545     size = GetFileVersionInfoSize(exefile, NULL);
1546     if (size == 0) {
1547     goto error;
1548     }
1549     buf = malloc(size);
1550     ZeroMemory(buf, size);
1551    
1552     if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1553     goto error;
1554     }
1555    
1556     ret = VerQueryValue(buf,
1557     "\\VarFileInfo\\Translation",
1558     (LPVOID *)&lplgcode, &unLen);
1559     if (ret == FALSE)
1560     goto error;
1561    
1562     for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1563     _snprintf(fmt, sizeof(fmt), "\\StringFileInfo\\%04x%04x\\FileVersion",
1564     lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1565     VerQueryValue(buf, fmt, &pbuf, &unLen);
1566     if (unLen > 0) { // get success
1567     int n, a, b, c, d;
1568    
1569     n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1570     if (n == 4) { // convert success
1571     *major = a;
1572     *minor = b;
1573     *release = c;
1574     *build = d;
1575     break;
1576     }
1577     }
1578     }
1579    
1580     free(buf);
1581     return;
1582    
1583     error:
1584     free(buf);
1585     *major = *minor = *release = *build = 0;
1586     }
1587    
1588 yutakakn 2728 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1589     {
1590     char buf[1024];
1591 yutakakn 2792 int a, b, c, d;
1592 yutakakn 2728
1593 yutakakn 2792 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1594     get_file_version("ttxssh.dll", &a, &b, &c, &d);
1595     _snprintf(buf, sizeof(buf), "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1596     SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1597    
1598 yutakakn 2782 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1599 yutakakn 2820 // ���������� (2005.5.11 yutaka)
1600     #ifdef OPENSSL_VERSION_TEXT
1601 yutakakn 2782 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1602 yutakakn 2820 #else
1603     SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1604     #endif
1605 yutakakn 2782
1606 yutakakn 2820 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1607     #ifdef ZLIB_VERSION
1608 yutakakn 2823 _snprintf(buf, sizeof(buf), "ZLib %s", ZLIB_VERSION);
1609 yutakakn 2820 #else
1610 yutakakn 2823 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1611 yutakakn 2820 #endif
1612     SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1613    
1614    
1615 yutakakn 2728 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1616     if (pvar->socket != INVALID_SOCKET) {
1617     if (SSHv1(pvar)) {
1618     SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1619     append_about_text(dlg, "Server ID: ", buf);
1620     SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1621     append_about_text(dlg, "Using protocol: ", buf);
1622     CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1623     append_about_text(dlg, "Encryption: ", buf);
1624     CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1625     append_about_text(dlg, "Server keys: ", buf);
1626     AUTH_get_auth_info(pvar, buf, sizeof(buf));
1627     append_about_text(dlg, "Authentication: ", buf);
1628     SSH_get_compression_info(pvar, buf, sizeof(buf));
1629     append_about_text(dlg, "Compression: ", buf);
1630    
1631     } else { // SSH2
1632     SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1633     append_about_text(dlg, "Server ID: ", buf);
1634    
1635     append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1636    
1637     SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1638     append_about_text(dlg, "Using protocol: ", buf);
1639    
1640     if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1641     strcpy(buf, KEX_DH1);
1642     } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1643     strcpy(buf, KEX_DH14);
1644     } else {
1645     strcpy(buf, KEX_DHGEX);
1646     }
1647     append_about_text(dlg, "KEX: ", buf);
1648    
1649     if (pvar->hostkey_type == KEY_DSA) {
1650     strcpy(buf, "ssh-dss");
1651     } else {
1652     strcpy(buf, "ssh-rsa");
1653     }
1654     append_about_text(dlg, "Host Key: ", buf);
1655    
1656 yutakakn 2758 // add HMAC algorithm (2004.12.17 yutaka)
1657     buf[0] = '\0';
1658     if (pvar->ctos_hmac == HMAC_SHA1) {
1659     strcat(buf, "hmac-sha1");
1660     } else if (pvar->ctos_hmac == HMAC_MD5) {
1661     strcat(buf, "hmac-md5");
1662     }
1663     strcat(buf, " to server, ");
1664     if (pvar->stoc_hmac == HMAC_SHA1) {
1665     strcat(buf, "hmac-sha1");
1666     } else if (pvar->stoc_hmac == HMAC_MD5) {
1667     strcat(buf, "hmac-md5");
1668     }
1669     strcat(buf, " from server");
1670     append_about_text(dlg, "HMAC: ", buf);
1671    
1672 yutakakn 2728 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1673     append_about_text(dlg, "Encryption: ", buf);
1674     CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1675     append_about_text(dlg, "Server keys: ", buf);
1676     AUTH_get_auth_info(pvar, buf, sizeof(buf));
1677     append_about_text(dlg, "Authentication: ", buf);
1678 yutakakn 2873
1679 yutakakn 2728 SSH_get_compression_info(pvar, buf, sizeof(buf));
1680 yutakakn 2873 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1681     append_about_text(dlg, "Delayed Compression: ", buf);
1682     } else {
1683     append_about_text(dlg, "Compression: ", buf);
1684     }
1685 yutakakn 2728
1686     }
1687     }
1688     }
1689    
1690     static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1691     LPARAM lParam)
1692     {
1693     switch (msg) {
1694     case WM_INITDIALOG:
1695     init_about_dlg((PTInstVar) lParam, dlg);
1696     return TRUE;
1697     case WM_COMMAND:
1698     switch (LOWORD(wParam)) {
1699     case IDOK:
1700     EndDialog(dlg, 1);
1701     return TRUE;
1702     case IDCANCEL: /* there isn't a cancel button, but other Windows
1703     UI things can send this message */
1704     EndDialog(dlg, 0);
1705     return TRUE;
1706     }
1707     break;
1708     }
1709    
1710     return FALSE;
1711     }
1712    
1713     static char FAR *get_cipher_name(int cipher)
1714     {
1715     switch (cipher) {
1716     case SSH_CIPHER_NONE:
1717     return "<ciphers below this line are disabled>";
1718     case SSH_CIPHER_RC4:
1719     return "RC4";
1720     case SSH_CIPHER_3DES:
1721     return "3DES";
1722     case SSH_CIPHER_DES:
1723     return "DES";
1724     case SSH_CIPHER_IDEA:
1725     return "IDEA";
1726     case SSH_CIPHER_TSS:
1727     return "TSS";
1728     case SSH_CIPHER_BLOWFISH:
1729     return "Blowfish";
1730    
1731     // for SSH2(yutaka)
1732     case SSH_CIPHER_AES128:
1733     return "AES128(SSH2)";
1734     case SSH_CIPHER_3DES_CBC:
1735     return "3DES-CBC(SSH2)";
1736    
1737     default:
1738     return NULL;
1739     }
1740     }
1741    
1742     static void set_move_button_status(HWND dlg)
1743     {
1744     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1745     int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1746     int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1747    
1748     EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1749     && curPos <= maxPos);
1750     EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1751     && curPos < maxPos);
1752     }
1753    
1754     static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1755     {
1756     HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1757     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1758     int i;
1759     int ch;
1760    
1761     SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1762     SendMessage(compressionControl, TBM_SETPOS, TRUE,
1763     pvar->settings.CompressionLevel);
1764    
1765     normalize_cipher_order(pvar->settings.CipherOrder);
1766    
1767     for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1768     int cipher = pvar->settings.CipherOrder[i] - '0';
1769     char FAR *name = get_cipher_name(cipher);
1770    
1771     if (name != NULL) {
1772     SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1773     }
1774     }
1775    
1776     SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1777     set_move_button_status(dlg);
1778    
1779     for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1780     i++) {
1781     }
1782     if (ch != 0) {
1783     pvar->settings.KnownHostsFiles[i] = 0;
1784     SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1785     pvar->settings.KnownHostsFiles);
1786     pvar->settings.KnownHostsFiles[i] = ch;
1787     SetDlgItemText(dlg, IDC_READONLYFILENAME,
1788     pvar->settings.KnownHostsFiles + i + 1);
1789     } else {
1790     SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1791     pvar->settings.KnownHostsFiles);
1792     }
1793 yutakakn 2789
1794     // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
1795     {
1796     char buf[10];
1797     _snprintf(buf, sizeof(buf), "%d", pvar->settings.ssh_heartbeat_overtime);
1798     SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
1799     }
1800    
1801 yutakakn 2728 }
1802    
1803     void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1804     char FAR * basename)
1805     {
1806     int filename_start = 0;
1807     int i;
1808     int ch;
1809    
1810     if (basename[0] == '\\' || basename[0] == '/'
1811     || (basename[0] != 0 && basename[1] == ':')) {
1812     strncpy(buf, basename, bufsize);
1813     buf[bufsize - 1] = 0;
1814     return;
1815     }
1816    
1817     GetModuleFileName(NULL, buf, bufsize);
1818     for (i = 0; (ch = buf[i]) != 0; i++) {
1819     if (ch == '\\' || ch == '/' || ch == ':') {
1820     filename_start = i + 1;
1821     }
1822     }
1823    
1824     if (bufsize > filename_start) {
1825     strncpy(buf + filename_start, basename, bufsize - filename_start);
1826     }
1827     buf[bufsize - 1] = 0;
1828     }
1829    
1830     int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1831     char FAR * basename)
1832     {
1833     char buf[1024];
1834     int filename_start = 0;
1835     int i;
1836     int ch, ch2;
1837    
1838     if (basename[0] != '\\' && basename[0] != '/'
1839     && (basename[0] == 0 || basename[1] != ':')) {
1840     strncpy(dest, basename, destsize);
1841     dest[destsize - 1] = 0;
1842     return strlen(dest);
1843     }
1844    
1845     GetModuleFileName(NULL, buf, sizeof(buf));
1846     for (i = 0; (ch = buf[i]) != 0; i++) {
1847     if (ch == '\\' || ch == '/' || ch == ':') {
1848     filename_start = i + 1;
1849     }
1850     }
1851    
1852     for (i = 0; i < filename_start; i++) {
1853     ch = toupper(buf[i]);
1854     ch2 = toupper(basename[i]);
1855    
1856     if (ch == ch2
1857     || ((ch == '\\' || ch == '/')
1858     && (ch2 == '\\' || ch2 == '/'))) {
1859     } else {
1860     break;
1861     }
1862     }
1863    
1864     if (i == filename_start) {
1865     strncpy(dest, basename + i, destsize);
1866     } else {
1867     strncpy(dest, basename, destsize);
1868     }
1869     dest[destsize - 1] = 0;
1870     return strlen(dest);
1871     }
1872    
1873     static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1874     {
1875     char buf[4096];
1876     char buf2[1024];
1877     HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1878     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1879     int i, j, buf2index, bufindex;
1880     int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1881    
1882     pvar->settings.CompressionLevel =
1883     (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1884    
1885     buf2index = 0;
1886     for (i = 0; i < count; i++) {
1887     int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1888    
1889     if (len > 0 && len < sizeof(buf)) { /* should always be true */
1890     buf[0] = 0;
1891     SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1892     for (j = 0;
1893     j <= SSH_CIPHER_MAX
1894     && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1895     }
1896     if (j <= SSH_CIPHER_MAX) {
1897     buf2[buf2index] = '0' + j;
1898     buf2index++;
1899     }
1900     }
1901     }
1902     buf2[buf2index] = 0;
1903     normalize_cipher_order(buf2);
1904     strcpy(pvar->settings.CipherOrder, buf2);
1905    
1906     buf[0] = 0;
1907     GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1908     j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1909     sizeof(pvar->settings.
1910     KnownHostsFiles), buf);
1911     buf[0] = 0;
1912     bufindex = 0;
1913     GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1914     for (i = 0; buf[i] != 0; i++) {
1915     if (buf[i] == ';') {
1916     buf[i] = 0;
1917     if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1918     pvar->settings.KnownHostsFiles[j] = ';';
1919     j++;
1920     j += copy_teraterm_dir_relative_path(pvar->settings.
1921     KnownHostsFiles + j,
1922     sizeof(pvar->settings.
1923     KnownHostsFiles)
1924     - j, buf + bufindex);
1925     }
1926     bufindex = i + 1;
1927     }
1928     }
1929     if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1930     pvar->settings.KnownHostsFiles[j] = ';';
1931     j++;
1932     copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1933     sizeof(pvar->settings.
1934     KnownHostsFiles) - j,
1935     buf + bufindex);
1936     }
1937 yutakakn 2789
1938     // get SSH HeartBeat(keep-alive)
1939     SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
1940     i = atoi(buf);
1941     if (i < 0)
1942     i = 60;
1943     pvar->settings.ssh_heartbeat_overtime = i;
1944    
1945 yutakakn 2728 }
1946    
1947     static void move_cur_sel_delta(HWND listbox, int delta)
1948     {
1949     int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1950     int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1951     int newPos = curPos + delta;
1952     char buf[1024];
1953    
1954     if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1955     int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1956    
1957     if (len > 0 && len < sizeof(buf)) { /* should always be true */
1958     buf[0] = 0;
1959     SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1960     SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1961     SendMessage(listbox, LB_INSERTSTRING, newPos,
1962     (LPARAM) (char FAR *) buf);
1963     SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1964     }
1965     }
1966     }
1967    
1968     static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1969     int readonly)
1970     {
1971     #ifdef TERATERM32
1972     OPENFILENAME params;
1973     char fullname_buf[2048] = "ssh_known_hosts";
1974    
1975     params.lStructSize = sizeof(OPENFILENAME);
1976     params.hwndOwner = parent;
1977     params.lpstrFilter = NULL;
1978     params.lpstrCustomFilter = NULL;
1979     params.nFilterIndex = 0;
1980     buf[0] = 0;
1981     params.lpstrFile = fullname_buf;
1982     params.nMaxFile = sizeof(fullname_buf);
1983     params.lpstrFileTitle = NULL;
1984     params.lpstrInitialDir = NULL;
1985     params.lpstrTitle =
1986     readonly ? "Choose a read-only known-hosts file to add" :
1987     "Choose a read/write known-hosts file";
1988     params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1989     | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1990     params.lpstrDefExt = NULL;
1991    
1992     if (GetOpenFileName(&params) != 0) {
1993     copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1994     return 1;
1995     } else {
1996     int err = CommDlgExtendedError();
1997    
1998     if (err != 0) {
1999     char buf[1024];
2000    
2001     _snprintf(buf, sizeof(buf),
2002     "Cannot show file dialog box: error %d", err);
2003     buf[sizeof(buf) - 1] = 0;
2004     MessageBox(parent, buf, "TTSSH Error",
2005     MB_OK | MB_ICONEXCLAMATION);
2006     }
2007    
2008     return 0;
2009     }
2010     #else
2011     return 0;
2012     #endif
2013     }
2014    
2015     static void choose_read_write_file(HWND dlg)
2016     {
2017     char buf[1024];
2018    
2019     if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2020     SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2021     }
2022     }
2023    
2024     static void choose_read_only_file(HWND dlg)
2025     {
2026     char buf[1024];
2027     char buf2[4096];
2028    
2029     if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2030     buf2[0] = 0;
2031     GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2032     if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2033     strncat(buf2, ";", sizeof(buf2));
2034     }
2035     strncat(buf2, buf, sizeof(buf2));
2036     SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2037     }
2038     }
2039    
2040     static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2041     LPARAM lParam)
2042     {
2043     switch (msg) {
2044     case WM_INITDIALOG:
2045     SetWindowLong(dlg, DWL_USER, lParam);
2046     init_setup_dlg((PTInstVar) lParam, dlg);
2047     return TRUE;
2048     case WM_COMMAND:
2049     switch (LOWORD(wParam)) {
2050     case IDOK:
2051     complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
2052     dlg);
2053     EndDialog(dlg, 1);
2054     return TRUE;
2055     case IDCANCEL: /* there isn't a cancel button, but other Windows
2056     UI things can send this message */
2057     EndDialog(dlg, 0);
2058     return TRUE;
2059     case IDC_SSHMOVECIPHERUP:
2060     move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2061     set_move_button_status(dlg);
2062     SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2063     return TRUE;
2064     case IDC_SSHMOVECIPHERDOWN:
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_SSHCIPHERPREFS:
2070     set_move_button_status(dlg);
2071     return TRUE;
2072     case IDC_CHOOSEREADWRITEFILE:
2073     choose_read_write_file(dlg);
2074     return TRUE;
2075     case IDC_CHOOSEREADONLYFILE:
2076     choose_read_only_file(dlg);
2077     return TRUE;
2078     }
2079     break;
2080     }
2081    
2082     return FALSE;
2083     }
2084    
2085 yutakakn 2816
2086     //
2087     // SSH key generator dialog (2005.4.10 yutaka)
2088     //
2089    
2090     typedef struct {
2091     RSA *rsa;
2092     DSA *dsa;
2093     } ssh_private_key_t;
2094    
2095     static ssh_private_key_t private_key = {NULL, NULL};
2096    
2097     typedef struct {
2098     RSA *rsa;
2099     DSA *dsa;
2100     } ssh_public_key_t;
2101    
2102     static ssh_public_key_t public_key = {NULL, NULL};;
2103    
2104     static void free_ssh_key(void)
2105     {
2106     // DSA_free(), RSA_free()��NULL���n�����������������B
2107     DSA_free(private_key.dsa);
2108     private_key.dsa = NULL;
2109     DSA_free(public_key.dsa);
2110     public_key.dsa = NULL;
2111    
2112     RSA_free(private_key.rsa);
2113     private_key.rsa = NULL;
2114     RSA_free(public_key.rsa);
2115     public_key.rsa = NULL;
2116     }
2117    
2118    
2119     static BOOL generate_ssh_key(enum hostkey_type type)
2120     {
2121     int bits = 1024;
2122    
2123     // if SSH key already is generated, should free the resource.
2124     free_ssh_key();
2125    
2126     if (type == KEY_RSA1 || type == KEY_RSA) {
2127     RSA *priv = NULL;
2128     RSA *pub = NULL;
2129    
2130     // private key
2131     priv = RSA_generate_key(bits, 35, NULL, NULL);
2132     if (priv == NULL)
2133     goto error;
2134     private_key.rsa = priv;
2135    
2136     // public key
2137     pub = RSA_new();
2138     pub->n = BN_new();
2139     pub->e = BN_new();
2140     if (pub->n == NULL || pub->e == NULL) {
2141     RSA_free(pub);
2142     goto error;
2143     }
2144    
2145     BN_copy(pub->n, priv->n);
2146     BN_copy(pub->e, priv->e);
2147     public_key.rsa = pub;
2148    
2149     } else if (type == KEY_DSA) {
2150     DSA *priv = NULL;
2151     DSA *pub = NULL;
2152    
2153     // private key
2154     priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2155     if (priv == NULL)
2156     goto error;
2157     if (!DSA_generate_key(priv)) {
2158     // TODO: free 'priv'?
2159     goto error;
2160     }
2161     private_key.dsa = priv;
2162    
2163     // public key
2164     pub = DSA_new();
2165     if (pub == NULL)
2166     goto error;
2167     pub->p = BN_new();
2168     pub->q = BN_new();
2169     pub->g = BN_new();
2170     pub->pub_key = BN_new();
2171     if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2172     DSA_free(pub);
2173     goto error;
2174     }
2175    
2176     BN_copy(pub->p, priv->p);
2177     BN_copy(pub->q, priv->q);
2178     BN_copy(pub->g, priv->g);
2179     BN_copy(pub->pub_key, priv->pub_key);
2180     public_key.dsa = pub;
2181    
2182     } else {
2183     goto error;
2184     }
2185    
2186     return TRUE;
2187    
2188     error:
2189     free_ssh_key();
2190     return FALSE;
2191     }
2192    
2193    
2194     //
2195     // RC4
2196     //
2197    
2198     /* Size of key to use */
2199     #define SEED_SIZE 20
2200    
2201     /* Number of bytes to reseed after */
2202     #define REKEY_BYTES (1 << 24)
2203    
2204     static int rc4_ready = 0;
2205     static RC4_KEY rc4;
2206    
2207     static void seed_rng(void)
2208     {
2209     if (RAND_status() != 1)
2210     return;
2211     }
2212    
2213     static void arc4random_stir(void)
2214     {
2215     unsigned char rand_buf[SEED_SIZE];
2216     int i;
2217    
2218     memset(&rc4, 0, sizeof(rc4));
2219     if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2220     //fatal("Couldn't obtain random bytes (error %ld)",
2221     // ERR_get_error());
2222     }
2223     RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2224    
2225     /*
2226     * Discard early keystream, as per recommendations in:
2227     * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2228     */
2229     for(i = 0; i <= 256; i += sizeof(rand_buf))
2230     RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2231    
2232     memset(rand_buf, 0, sizeof(rand_buf));
2233    
2234     rc4_ready = REKEY_BYTES;
2235     }
2236    
2237     static unsigned int arc4random(void)
2238     {
2239     unsigned int r = 0;
2240     static int first_time = 1;
2241    
2242     if (rc4_ready <= 0) {
2243     if (first_time) {
2244     seed_rng();
2245     }
2246     first_time = 0;
2247     arc4random_stir();
2248     }
2249    
2250     RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2251    
2252     rc4_ready -= sizeof(r);
2253    
2254     return(r);
2255     }
2256    
2257     //
2258     // SSH1 3DES
2259     //
2260     /*
2261     * This is used by SSH1:
2262     *
2263     * What kind of triple DES are these 2 routines?
2264     *
2265     * Why is there a redundant initialization vector?
2266     *
2267     * If only iv3 was used, then, this would till effect have been
2268     * outer-cbc. However, there is also a private iv1 == iv2 which
2269     * perhaps makes differential analysis easier. On the other hand, the
2270     * private iv1 probably makes the CRC-32 attack ineffective. This is a
2271     * result of that there is no longer any known iv1 to use when
2272     * choosing the X block.
2273     */
2274     struct ssh1_3des_ctx
2275     {
2276     EVP_CIPHER_CTX k1, k2, k3;
2277     };
2278    
2279     static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2280     {
2281     struct ssh1_3des_ctx *c;
2282     u_char *k1, *k2, *k3;
2283    
2284     if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2285     c = malloc(sizeof(*c));
2286     EVP_CIPHER_CTX_set_app_data(ctx, c);
2287     }
2288     if (key == NULL)
2289     return (1);
2290     if (enc == -1)
2291     enc = ctx->encrypt;
2292     k1 = k2 = k3 = (u_char *) key;
2293     k2 += 8;
2294     if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2295     if (enc)
2296     k3 += 16;
2297     else
2298     k1 += 16;
2299     }
2300     EVP_CIPHER_CTX_init(&c->k1);
2301     EVP_CIPHER_CTX_init(&c->k2);
2302     EVP_CIPHER_CTX_init(&c->k3);
2303     if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2304     EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2305     EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2306     memset(c, 0, sizeof(*c));
2307     free(c);
2308     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2309     return (0);
2310     }
2311     return (1);
2312     }
2313    
2314     static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2315     {
2316     struct ssh1_3des_ctx *c;
2317    
2318     if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2319     //error("ssh1_3des_cbc: no context");
2320     return (0);
2321     }
2322     if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2323     EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2324     EVP_Cipher(&c->k3, dest, dest, len) == 0)
2325     return (0);
2326     return (1);
2327     }
2328    
2329     static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2330     {
2331     struct ssh1_3des_ctx *c;
2332    
2333     if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2334     EVP_CIPHER_CTX_cleanup(&c->k1);
2335     EVP_CIPHER_CTX_cleanup(&c->k2);
2336     EVP_CIPHER_CTX_cleanup(&c->k3);
2337     memset(c, 0, sizeof(*c));
2338     free(c);
2339     EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2340     }
2341     return (1);
2342     }
2343    
2344     void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2345     {
2346     struct ssh1_3des_ctx *c;
2347    
2348     if (len != 24)
2349     //fatal("%s: bad 3des iv length: %d", __func__, len);
2350     ;
2351    
2352     if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2353     //fatal("%s: no 3des context", __func__);
2354     ;
2355    
2356     if (doset) {
2357     //debug3("%s: Installed 3DES IV", __func__);
2358     memcpy(c->k1.iv, iv, 8);
2359     memcpy(c->k2.iv, iv + 8, 8);
2360     memcpy(c->k3.iv, iv + 16, 8);
2361     } else {
2362     //debug3("%s: Copying 3DES IV", __func__);
2363     memcpy(iv, c->k1.iv, 8);
2364     memcpy(iv + 8, c->k2.iv, 8);
2365     memcpy(iv + 16, c->k3.iv, 8);
2366     }
2367     }
2368    
2369     const EVP_CIPHER *evp_ssh1_3des(void)
2370     {
2371     static EVP_CIPHER ssh1_3des;
2372    
2373     memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2374     ssh1_3des.nid = NID_undef;
2375     ssh1_3des.block_size = 8;
2376     ssh1_3des.iv_len = 0;
2377     ssh1_3des.key_len = 16;
2378     ssh1_3des.init = ssh1_3des_init;
2379     ssh1_3des.cleanup = ssh1_3des_cleanup;
2380     ssh1_3des.do_cipher = ssh1_3des_cbc;
2381     ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2382     return (&ssh1_3des);
2383     }
2384    
2385     static void ssh_make_comment(char *comment, int maxlen)
2386     {
2387     char user[UNLEN + 1], host[128];
2388     DWORD dwSize;
2389     WSADATA wsaData;
2390     int ret;
2391    
2392     // get Windows logon user name
2393     dwSize = sizeof(user);
2394     if (GetUserName(user, &dwSize) == 0) {
2395     strcpy(user, "yutaka");
2396     }
2397    
2398     // get local hostname (by WinSock)
2399     ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2400     if (ret == 0) {
2401     if (gethostname(host, sizeof(host)) != 0) {
2402     ret = WSAGetLastError();
2403     }
2404     WSACleanup();
2405     }
2406     if (ret != 0) {
2407     strcpy(host, "sai");
2408     }
2409    
2410     _snprintf(comment, maxlen, "%s@%s", user, host);
2411     }
2412    
2413     // uuencode (rfc1521)
2414 yutakakn 2856 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2415 yutakakn 2816