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