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 2909 - (hide annotations) (download) (as text)
Mon Sep 18 06:14:48 2006 UTC (17 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 90139 byte(s)
ポートフォワードしているウインドウから新規接続するとエラーが出る問題を修正した。

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