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 2907 - (hide annotations) (download) (as text)
Sat Sep 16 07:24:06 2006 UTC (17 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 89577 byte(s)
/ssh1, /ssh2, /telnet オプションを追加した。

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