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 2897 - (hide annotations) (download) (as text)
Wed Aug 9 15:13:17 2006 UTC (17 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 87987 byte(s)
ttermpro.exe のアイコンハンドルを取得できない問題を修正した

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