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 2908 - (hide annotations) (download) (as text)
Mon Sep 18 05:08:04 2006 UTC (17 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 89979 byte(s)
コマンドラインパラメータ '/ask4passwd' を追加した。

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