Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3159 - (show annotations) (download) (as text)
Tue Nov 18 06:24:09 2008 UTC (15 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118555 byte(s)
SSH2 の AES CTR をサポート(yasuhide)
http://jvn.jp/niscc/CPNI-957037/

1 /*
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 /* Tera Term extension mechanism
30 Robert O'Callahan (roc+tt@cs.cmu.edu)
31
32 Tera Term by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
33 */
34
35 #include "ttxssh.h"
36 #include "fwdui.h"
37 #include "util.h"
38 #include "ssh.h"
39 #include "ttcommon.h"
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <io.h>
45 #include <fcntl.h>
46 #include <sys/stat.h>
47 #include <time.h>
48
49 #include "resource.h"
50 #include <commctrl.h>
51 #include <commdlg.h>
52 #ifndef NO_INET6
53 #include <winsock2.h>
54 static char FAR *ProtocolFamilyList[] = { "UNSPEC", "IPv6", "IPv4", NULL };
55 #else
56 #include <winsock.h>
57 #endif /* NO_INET6 */
58
59 #include <Lmcons.h>
60
61 // include OpenSSL header file
62 #include <openssl/opensslv.h>
63 #include <openssl/evp.h>
64 #include <openssl/rsa.h>
65 #include <openssl/dsa.h>
66 #include <openssl/bn.h>
67 #include <openssl/pem.h>
68 #include <openssl/rand.h>
69 #include <openssl/rc4.h>
70 #include <openssl/md5.h>
71
72 // include ZLib header file
73 #include <zlib.h>
74
75 #include "buffer.h"
76 #include "cipher.h"
77
78 #include "sftp.h"
79
80 #define MATCH_STR(s, o) strncmp((s), (o), NUM_ELEM(o) - 1)
81 #define MATCH_STR_I(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
82
83 /* This extension implements SSH, so we choose a load order in the
84 "protocols" range. */
85 #define ORDER 2500
86
87 static HICON SecureLargeIcon = NULL;
88 static HICON SecureSmallIcon = NULL;
89
90 static HFONT DlgHostFont;
91 static HFONT DlgAboutFont;
92 static HFONT DlgSetupFont;
93 static HFONT DlgKeygenFont;
94
95 static TInstVar FAR *pvar;
96
97 /* WIN32 allows multiple instances of a DLL */
98 static TInstVar InstVar;
99 #define GET_VAR()
100
101 /*
102 This code makes lots of assumptions about the order in which Tera Term
103 does things, and how. A key assumption is that the Notification window
104 passed into WSAAsyncSelect is the main terminal window. We also assume
105 that the socket used in the first WSAconnect is the main session socket.
106 */
107
108 static void init_TTSSH(PTInstVar pvar)
109 {
110 pvar->socket = INVALID_SOCKET;
111 pvar->OldLargeIcon = NULL;
112 pvar->OldSmallIcon = NULL;
113 pvar->NotificationWindow = NULL;
114 pvar->hostdlg_activated = FALSE;
115 pvar->socket = INVALID_SOCKET;
116 pvar->NotificationWindow = NULL;
117 pvar->protocol_major = 0;
118 pvar->protocol_minor = 0;
119
120 PKT_init(pvar);
121 SSH_init(pvar);
122 CRYPT_init(pvar);
123 AUTH_init(pvar);
124 HOSTS_init(pvar);
125 FWD_init(pvar);
126 FWDUI_init(pvar);
127
128 ssh_heartbeat_lock_initialize();
129 }
130
131 static void uninit_TTSSH(PTInstVar pvar)
132 {
133 halt_ssh_heartbeat_thread(pvar);
134
135 ssh2_channel_free();
136
137 SSH_end(pvar);
138 PKT_end(pvar);
139 AUTH_end(pvar);
140 CRYPT_end(pvar);
141 HOSTS_end(pvar);
142 FWD_end(pvar);
143 FWDUI_end(pvar);
144
145 if (pvar->OldLargeIcon != NULL) {
146 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
147 (LPARAM) pvar->OldLargeIcon);
148 pvar->OldLargeIcon = NULL;
149 }
150 if (pvar->OldSmallIcon != NULL) {
151 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
152 (LPARAM) pvar->OldSmallIcon);
153 pvar->OldSmallIcon = NULL;
154 }
155
156 ssh_heartbeat_lock_finalize();
157 }
158
159 static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv)
160 {
161 pvar->settings = *pvar->ts_SSH;
162 pvar->ts = ts;
163 pvar->cv = cv;
164 pvar->fatal_error = FALSE;
165 pvar->showing_err = FALSE;
166 pvar->err_msg = NULL;
167
168 init_TTSSH(pvar);
169 }
170
171 static void normalize_cipher_order(char FAR * buf)
172 {
173 char ciphers_listed[SSH_CIPHER_MAX + 1];
174 char ciphers_allowed[SSH_CIPHER_MAX + 1];
175 int i, j;
176
177 /* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
178 We *never* allow no encryption. */
179 #if 0
180 static char default_ciphers[] = {
181 SSH_CIPHER_3DES,
182 SSH_CIPHER_NONE,
183 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
184 };
185 #else
186 // for SSH2(yutaka)
187 static char default_ciphers[] = {
188 SSH2_CIPHER_AES128_CBC,
189 SSH2_CIPHER_3DES_CBC,
190 SSH2_CIPHER_BLOWFISH_CBC,
191 SSH2_CIPHER_AES192_CBC,
192 SSH2_CIPHER_AES256_CBC,
193 SSH2_CIPHER_AES128_CTR,
194 SSH2_CIPHER_AES192_CTR,
195 SSH2_CIPHER_AES256_CTR,
196 SSH_CIPHER_3DES,
197 SSH_CIPHER_NONE,
198 SSH_CIPHER_DES,
199 SSH_CIPHER_BLOWFISH
200 };
201 #endif
202
203 memset(ciphers_listed, 0, sizeof(ciphers_listed));
204
205 memset(ciphers_allowed, 0, sizeof(ciphers_allowed));
206 for (i = 0; i < NUM_ELEM(default_ciphers); i++) {
207 ciphers_allowed[default_ciphers[i]] = 1;
208 }
209
210 for (i = 0; buf[i] != 0; i++) {
211 int cipher_num = buf[i] - '0';
212
213 if (cipher_num < 0 || cipher_num > SSH_CIPHER_MAX
214 || !ciphers_allowed[cipher_num]
215 || ciphers_listed[cipher_num]) {
216 memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
217 i--;
218 } else {
219 ciphers_listed[cipher_num] = 1;
220 }
221 }
222
223 for (j = 0; j < NUM_ELEM(default_ciphers); j++) {
224 int cipher_num = default_ciphers[j];
225
226 if (!ciphers_listed[cipher_num]) {
227 buf[i] = cipher_num + '0';
228 i++;
229 }
230 }
231
232 buf[i] = 0;
233 }
234
235 /* Remove local settings from the shared memory block. */
236 static void clear_local_settings(PTInstVar pvar)
237 {
238 pvar->ts_SSH->TryDefaultAuth = FALSE;
239 }
240
241 static BOOL read_BOOL_option(PCHAR fileName, char FAR * keyName, BOOL def)
242 {
243 char buf[1024];
244
245 buf[0] = 0;
246 GetPrivateProfileString("TTSSH", keyName, "", buf, sizeof(buf),
247 fileName);
248 if (buf[0] == 0) {
249 return def;
250 } else {
251 return atoi(buf) != 0 ||
252 _stricmp(buf, "yes") == 0 ||
253 _stricmp(buf, "y") == 0;
254 }
255 }
256
257 static void read_string_option(PCHAR fileName, char FAR * keyName,
258 char FAR * def, char FAR * buf, int bufSize)
259 {
260
261 buf[0] = 0;
262 GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
263 }
264
265 static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
266 {
267 char buf[1024];
268 TS_SSH FAR *settings = pvar->ts_SSH;
269
270 #define READ_STD_STRING_OPTION(name) \
271 read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
272
273 settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
274
275 buf[0] = 0;
276 GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
277 fileName);
278 settings->CompressionLevel = atoi(buf);
279 if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
280 settings->CompressionLevel = 0;
281 }
282
283 READ_STD_STRING_OPTION(DefaultUserName);
284 READ_STD_STRING_OPTION(DefaultForwarding);
285 READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
286 READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
287 READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
288
289 READ_STD_STRING_OPTION(CipherOrder);
290 normalize_cipher_order(settings->CipherOrder);
291
292 read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
293 settings->KnownHostsFiles,
294 sizeof(settings->KnownHostsFiles));
295
296 buf[0] = 0;
297 GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
298 sizeof(buf), fileName);
299 settings->DefaultAuthMethod = atoi(buf);
300 if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
301 && settings->DefaultAuthMethod != SSH_AUTH_RSA
302 && settings->DefaultAuthMethod != SSH_AUTH_TIS // add (2005.3.12 yutaka)
303 && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS
304 && settings->DefaultAuthMethod != SSH_AUTH_PAGEANT) {
305 /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
306 selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
307 when the dialog box has rhosts selected and an host private key file
308 is supplied. */
309 settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
310 }
311
312 buf[0] = 0;
313 GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
314 fileName);
315 settings->LogLevel = atoi(buf);
316
317 buf[0] = 0;
318 GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
319 sizeof(buf), fileName);
320 settings->WriteBufferSize = atoi(buf);
321 if (settings->WriteBufferSize <= 0) {
322 settings->WriteBufferSize = 2 * 1024 * 1024;
323 }
324
325 settings->LocalForwardingIdentityCheck =
326 read_BOOL_option(fileName, "LocalForwardingIdentityCheck", TRUE);
327
328 // SSH protocol version (2004.10.11 yutaka)
329 // default is SSH2 (2004.11.30 yutaka)
330 settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
331
332 // SSH heartbeat time(second) (2004.12.11 yutaka)
333 settings->ssh_heartbeat_overtime = GetPrivateProfileInt("TTSSH", "HeartBeat", 60, fileName);
334
335 // �p�X���[�h�F�����������J���F�����g���p�X���[�h����������������������������������
336 // �\���B(2006.8.5 yutaka)
337 settings->remember_password = GetPrivateProfileInt("TTSSH", "RememberPassword", 1, fileName);
338
339 // �������F���_�C�A���O���T�|�[�g�������������\�b�h���`�F�b�N���A
340 // ���������\�b�h���O���C�A�E�g���� (2007.9.24 maya)
341 settings->CheckAuthListFirst = read_BOOL_option(fileName, "CheckAuthListFirst", FALSE);
342
343 // 768bit ������ RSA ���������T�[�o�����������L�������� (2008.9.11 maya)
344 settings->EnableRsaShortKeyServer = read_BOOL_option(fileName, "EnableRsaShortKeyServer", FALSE);
345
346 clear_local_settings(pvar);
347 }
348
349 static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
350 TS_SSH FAR * settings, BOOL copy_forward)
351 {
352 char buf[1024];
353
354 WritePrivateProfileString("TTSSH", "Enabled",
355 settings->Enabled ? "1" : "0", fileName);
356
357 _itoa(settings->CompressionLevel, buf, 10);
358 WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
359
360 WritePrivateProfileString("TTSSH", "DefaultUserName",
361 settings->DefaultUserName, fileName);
362
363 if (copy_forward) {
364 WritePrivateProfileString("TTSSH", "DefaultForwarding",
365 settings->DefaultForwarding, fileName);
366 }
367
368 WritePrivateProfileString("TTSSH", "CipherOrder",
369 settings->CipherOrder, fileName);
370
371 WritePrivateProfileString("TTSSH", "KnownHostsFiles",
372 settings->KnownHostsFiles, fileName);
373
374 WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
375 settings->DefaultRhostsLocalUserName,
376 fileName);
377
378 WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
379 settings->DefaultRhostsHostPrivateKeyFile,
380 fileName);
381
382 WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
383 settings->DefaultRSAPrivateKeyFile,
384 fileName);
385
386 _itoa(settings->DefaultAuthMethod, buf, 10);
387 WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
388
389 _itoa(settings->LogLevel, buf, 10);
390 WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
391
392 _itoa(settings->WriteBufferSize, buf, 10);
393 WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
394
395 WritePrivateProfileString("TTSSH", "LocalForwardingIdentityCheck",
396 settings->LocalForwardingIdentityCheck ? "1" : "0",
397 fileName);
398
399 // SSH protocol version (2004.10.11 yutaka)
400 WritePrivateProfileString("TTSSH", "ProtocolVersion",
401 settings->ssh_protocol_version==2 ? "2" : "1",
402 fileName);
403
404 // SSH heartbeat time(second) (2004.12.11 yutaka)
405 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
406 "%d", settings->ssh_heartbeat_overtime);
407 WritePrivateProfileString("TTSSH", "HeartBeat", buf, fileName);
408
409 // Remember password (2006.8.5 yutaka)
410 WritePrivateProfileString("TTSSH", "RememberPassword",
411 settings->remember_password ? "1" : "0",
412 fileName);
413
414 // �������F���_�C�A���O���T�|�[�g�������������\�b�h���`�F�b�N���A
415 // ���������\�b�h���O���C�A�E�g���� (2007.9.24 maya)
416 WritePrivateProfileString("TTSSH", "CheckAuthListFirst",
417 settings->CheckAuthListFirst ? "1" : "0", fileName);
418
419 // 768bit ������ RSA ���������T�[�o�����������L�������� (2008.9.11 maya)
420 WritePrivateProfileString("TTSSH", "EnableRsaShortKeyServer",
421 settings->EnableRsaShortKeyServer ? "1" : "0", fileName);
422 }
423
424
425 /* find free port in all protocol family */
426 static unsigned short find_local_port(PTInstVar pvar)
427 {
428 int tries;
429 #ifndef NO_INET6
430 SOCKET connecter;
431 struct addrinfo hints;
432 struct addrinfo FAR *res;
433 struct addrinfo FAR *res0;
434 unsigned short port;
435 char pname[NI_MAXHOST];
436 #endif /* NO_INET6 */
437
438 if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
439 return 0;
440 }
441
442 /* The random numbers here are only used to try to get fresh
443 ports across runs (dangling ports can cause bind errors
444 if we're unlucky). They do not need to be (and are not)
445 cryptographically strong.
446 */
447 srand((unsigned) GetTickCount());
448
449 #ifndef NO_INET6
450 for (tries = 20; tries > 0; tries--) {
451 memset(&hints, 0, sizeof(hints));
452 hints.ai_family = pvar->ts->ProtocolFamily;
453 hints.ai_flags = AI_PASSIVE;
454 hints.ai_socktype = SOCK_STREAM;
455 port = (unsigned) rand() % 512 + 512;
456 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", (int) port);
457 if (getaddrinfo(NULL, pname, &hints, &res0)) {
458 return 0;
459 /* NOT REACHED */
460 }
461
462 for (res = res0; res; res = res->ai_next) {
463 if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
464 continue;
465
466 connecter =
467 socket(res->ai_family, res->ai_socktype, res->ai_protocol);
468 if (connecter == INVALID_SOCKET) {
469 freeaddrinfo(res0);
470 return 0;
471 }
472
473 if (bind(connecter, res->ai_addr, res->ai_addrlen) !=
474 SOCKET_ERROR) {
475 return port;
476 freeaddrinfo(res0);
477 closesocket(connecter);
478 } else if (WSAGetLastError() != WSAEADDRINUSE) {
479 closesocket(connecter);
480 freeaddrinfo(res0);
481 return 0;
482 }
483
484 closesocket(connecter);
485 }
486 freeaddrinfo(res0);
487 }
488
489 return 0;
490 #else
491 for (tries = 20; tries > 0; tries--) {
492 SOCKET connecter = socket(AF_INET, SOCK_STREAM, 0);
493 struct sockaddr_in connecter_addr;
494
495 connecter_addr.sin_family = AF_INET;
496 connecter_addr.sin_port = (unsigned) rand() % 512 + 512;
497 connecter_addr.sin_addr.s_addr = htonl(INADDR_ANY);
498
499 if (connecter == INVALID_SOCKET) {
500 return 0;
501 }
502
503 if (bind
504 (connecter, (struct sockaddr FAR *) &connecter_addr,
505 sizeof(connecter_addr)) != SOCKET_ERROR) {
506 closesocket(connecter);
507 return connecter_addr.sin_port;
508 } else if (WSAGetLastError() != WSAEADDRINUSE) {
509 closesocket(connecter);
510 return 0;
511 }
512
513 closesocket(connecter);
514 }
515
516 return 0;
517 #endif /* NO_INET6 */
518 }
519
520 static int PASCAL FAR TTXconnect(SOCKET s,
521 const struct sockaddr FAR * name,
522 int namelen)
523 {
524 GET_VAR();
525
526 #ifndef NO_INET6
527 if (pvar->socket == INVALID_SOCKET) {
528 struct sockaddr_storage ss;
529 int len;
530
531 pvar->socket = s;
532
533 memset(&ss, 0, sizeof(ss));
534 switch (pvar->ts->ProtocolFamily) {
535 case AF_INET:
536 len = sizeof(struct sockaddr_in);
537 ((struct sockaddr_in FAR *) &ss)->sin_family = AF_INET;
538 ((struct sockaddr_in FAR *) &ss)->sin_addr.s_addr = INADDR_ANY;
539 ((struct sockaddr_in FAR *) &ss)->sin_port =
540 htons(find_local_port(pvar));
541 break;
542 case AF_INET6:
543 len = sizeof(struct sockaddr_in6);
544 ((struct sockaddr_in6 FAR *) &ss)->sin6_family = AF_INET6;
545 #if 0 /* symbol "in6addr_any" is not included in wsock32.lib */
546 /* if wsock32.lib will be linked, we can't refer "in6addr_any" */
547 ((struct sockaddr_in6 FAR *) &ss)->sin6_addr = in6addr_any;
548 #else
549 memset(&((struct sockaddr_in6 FAR *) &ss)->sin6_addr, 0,
550 sizeof(struct in_addr6));
551 #endif /* 0 */
552 ((struct sockaddr_in6 FAR *) &ss)->sin6_port =
553 htons(find_local_port(pvar));
554 break;
555 default:
556 /* NOT REACHED */
557 break;
558 }
559
560 bind(s, (struct sockaddr FAR *) &ss, len);
561 }
562 #else
563 if (pvar->socket == INVALID_SOCKET) {
564 struct sockaddr_in addr;
565
566 pvar->socket = s;
567
568 addr.sin_family = AF_INET;
569 addr.sin_port = htons(find_local_port(pvar));
570 addr.sin_addr.s_addr = INADDR_ANY;
571 memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
572
573 bind(s, (struct sockaddr FAR *) &addr, sizeof(addr));
574 }
575 #endif /* NO_INET6 */
576
577 return (pvar->Pconnect) (s, name, namelen);
578 }
579
580 static int PASCAL FAR TTXWSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
581 long lEvent)
582 {
583 GET_VAR();
584
585 if (s == pvar->socket) {
586 pvar->notification_events = lEvent;
587 pvar->notification_msg = wMsg;
588
589 if (pvar->NotificationWindow == NULL) {
590 pvar->NotificationWindow = hWnd;
591 AUTH_advance_to_next_cred(pvar);
592 }
593 }
594
595 return (pvar->PWSAAsyncSelect) (s, hWnd, wMsg, lEvent);
596 }
597
598 static int PASCAL FAR TTXrecv(SOCKET s, char FAR * buf, int len, int flags)
599 {
600 GET_VAR();
601
602 if (s == pvar->socket) {
603 int ret;
604
605 ssh_heartbeat_lock();
606 ret = PKT_recv(pvar, buf, len);
607 ssh_heartbeat_unlock();
608 return (ret);
609
610 } else {
611 return (pvar->Precv) (s, buf, len, flags);
612 }
613 }
614
615 static int PASCAL FAR TTXsend(SOCKET s, char const FAR * buf, int len,
616 int flags)
617 {
618 GET_VAR();
619
620 if (s == pvar->socket) {
621 ssh_heartbeat_lock();
622 SSH_send(pvar, buf, len);
623 ssh_heartbeat_unlock();
624 return len;
625 } else {
626 return (pvar->Psend) (s, buf, len, flags);
627 }
628 }
629
630 void notify_established_secure_connection(PTInstVar pvar)
631 {
632 int fuLoad = LR_DEFAULTCOLOR;
633
634 if (is_NT4()) {
635 fuLoad = LR_VGACOLOR;
636 }
637
638 // LoadIcon �������� LoadImage ���g�����������A
639 // 16x16 ���A�C�R���������I�������������������� (2006.8.9 maya)
640 if (SecureLargeIcon == NULL) {
641 SecureLargeIcon = LoadImage(hInst, MAKEINTRESOURCE(IDI_SECURETT),
642 IMAGE_ICON, 0, 0, fuLoad);
643 }
644 if (SecureSmallIcon == NULL) {
645 SecureSmallIcon = LoadImage(hInst, MAKEINTRESOURCE(IDI_SECURETT),
646 IMAGE_ICON, 16, 16, fuLoad);
647 }
648
649 if (SecureLargeIcon != NULL && SecureSmallIcon != NULL) {
650 // �������A�C�R���� WNDCLASS ���Z�b�g�����������������o���������� (2006.8.10 maya)
651 pvar->OldLargeIcon =
652 (HICON) GetClassLong(pvar->NotificationWindow, GCL_HICON);
653 pvar->OldSmallIcon =
654 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
655 ICON_SMALL, 0);
656
657 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
658 (LPARAM) SecureLargeIcon);
659 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
660 (LPARAM) SecureSmallIcon);
661 }
662
663 notify_verbose_message(pvar, "Entering secure mode",
664 LOG_LEVEL_VERBOSE);
665 }
666
667 void notify_closed_connection(PTInstVar pvar)
668 {
669 SSH_notify_disconnecting(pvar, NULL);
670 AUTH_notify_disconnecting(pvar);
671 HOSTS_notify_disconnecting(pvar);
672
673 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
674 pvar->socket, MAKELPARAM(FD_CLOSE, 0));
675
676 }
677
678 static void add_err_msg(PTInstVar pvar, char FAR * msg)
679 {
680 if (pvar->err_msg != NULL) {
681 int buf_len = strlen(pvar->err_msg) + 3 + strlen(msg);
682 char FAR *buf = (char FAR *) malloc(buf_len);
683
684 strncpy_s(buf, buf_len, pvar->err_msg, _TRUNCATE);
685 strncat_s(buf, buf_len, "\n\n", _TRUNCATE);
686 strncat_s(buf, buf_len, msg, _TRUNCATE);
687 free(pvar->err_msg);
688 pvar->err_msg = buf;
689 } else {
690 pvar->err_msg = _strdup(msg);
691 }
692 }
693
694 void notify_nonfatal_error(PTInstVar pvar, char FAR * msg)
695 {
696 if (!pvar->showing_err) {
697 // �������������������m���E�B���h�E�����������A�f�X�N�g�b�v���I�[�i�[������
698 // ���b�Z�[�W�{�b�N�X���o���������B(2006.6.11 yutaka)
699 if (pvar->NotificationWindow == NULL) {
700 UTIL_get_lang_msg("MSG_ERROR_NONFAITAL", pvar,
701 "Tera Term: not fatal error");
702 MessageBox(NULL, msg, pvar->ts->UIMsg, MB_OK|MB_ICONINFORMATION);
703 msg[0] = '\0';
704
705 } else {
706 PostMessage(pvar->NotificationWindow, WM_COMMAND,
707 ID_SSHASYNCMESSAGEBOX, 0);
708 }
709 }
710 if (msg[0] != 0) {
711 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
712 add_err_msg(pvar, msg);
713 }
714 }
715
716 void notify_fatal_error(PTInstVar pvar, char FAR * msg)
717 {
718 if (msg[0] != 0) {
719 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
720 add_err_msg(pvar, msg);
721 }
722
723 if (!pvar->fatal_error) {
724 pvar->fatal_error = TRUE;
725
726 SSH_notify_disconnecting(pvar, msg);
727 AUTH_notify_disconnecting(pvar);
728 HOSTS_notify_disconnecting(pvar);
729
730 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
731 pvar->socket, MAKELPARAM(FD_CLOSE,
732 (pvar->PWSAGetLastError) ()));
733 }
734 }
735
736 void notify_verbose_message(PTInstVar pvar, char FAR * msg, int level)
737 {
738 if (level <= pvar->session_settings.LogLevel) {
739 char buf[1024];
740 int file;
741
742 get_teraterm_dir_relative_name(buf, NUM_ELEM(buf), "TTSSH.LOG");
743 file = _open(buf, _O_RDWR | _O_APPEND | _O_CREAT | _O_TEXT,
744 _S_IREAD | _S_IWRITE);
745
746 if (file >= 0) {
747 _write(file, msg, strlen(msg));
748 _write(file, "\n", 1);
749 _close(file);
750 }
751 }
752 }
753
754 static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks)
755 {
756 GET_VAR();
757
758 if (pvar->settings.Enabled) {
759 char buf[1024] = "\n---------------------------------------------------------------------\nInitiating SSH session at ";
760 struct tm FAR *newtime;
761 time_t long_time;
762
763 // TCPLocalEcho/TCPCRSend ������������ (maya 2007.4.25)
764 pvar->ts->DisableTCPEchoCR = TRUE;
765
766 pvar->session_settings = pvar->settings;
767
768 time(&long_time);
769 newtime = localtime(&long_time);
770 strncat_s(buf, sizeof(buf), asctime(newtime), _TRUNCATE);
771 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
772
773 FWDUI_load_settings(pvar);
774
775 pvar->cv->TelAutoDetect = FALSE;
776 /* This next line should not be needed because Tera Term's
777 CommLib should find ts->Telnet == 0 ... but we'll do this
778 just to be on the safe side. */
779 pvar->cv->TelFlag = FALSE;
780
781 pvar->Precv = *hooks->Precv;
782 pvar->Psend = *hooks->Psend;
783 pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
784 pvar->Pconnect = *hooks->Pconnect;
785 pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
786
787 *hooks->Precv = TTXrecv;
788 *hooks->Psend = TTXsend;
789 *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
790 *hooks->Pconnect = TTXconnect;
791
792 SSH_open(pvar);
793 HOSTS_open(pvar);
794 FWDUI_open(pvar);
795
796 // ������ myproposal �����f���������A�������O�����������B (2006.6.26 maya)
797 SSH2_update_cipher_myproposal(pvar);
798 SSH2_update_compression_myproposal(pvar);
799 }
800 }
801
802 static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks)
803 {
804 GET_VAR();
805
806 if (pvar->session_settings.Enabled) {
807 pvar->socket = INVALID_SOCKET;
808
809 notify_verbose_message(pvar, "Terminating SSH session...",
810 LOG_LEVEL_VERBOSE);
811
812 *hooks->Precv = pvar->Precv;
813 *hooks->Psend = pvar->Psend;
814 *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
815 *hooks->Pconnect = pvar->Pconnect;
816 }
817
818 uninit_TTSSH(pvar);
819 init_TTSSH(pvar);
820 }
821
822 static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
823 {
824 for (; from <= to; from++) {
825 EnableWindow(GetDlgItem(dlg, from), enabled);
826 }
827 }
828
829 // C-p/C-n/C-b/C-f/C-a/C-e ���T�|�[�g (2007.9.5 maya)
830 // C-d/C-k ���T�|�[�g (2007.10.3 yutaka)
831 // �h���b�v�_�E���������G�f�B�b�g�R���g���[����
832 // �T�u�N���X�������������E�C���h�E�v���V�[�W��
833 WNDPROC OrigHostnameEditProc; // Original window procedure
834 LRESULT CALLBACK HostnameEditProc(HWND dlg, UINT msg,
835 WPARAM wParam, LPARAM lParam)
836 {
837 HWND parent;
838 int max, select, len;
839 char *str, *orgstr;
840
841 switch (msg) {
842 // �L�[�����������������m����
843 case WM_KEYDOWN:
844 if (GetKeyState(VK_CONTROL) < 0) {
845 switch (wParam) {
846 case 0x50: // Ctrl+p ... up
847 parent = GetParent(dlg);
848 select = SendMessage(parent, CB_GETCURSEL, 0, 0);
849 if (select > 0) {
850 PostMessage(parent, CB_SETCURSEL, select - 1, 0);
851 }
852 return 0;
853 case 0x4e: // Ctrl+n ... down
854 parent = GetParent(dlg);
855 max = SendMessage(parent, CB_GETCOUNT, 0, 0);
856 select = SendMessage(parent, CB_GETCURSEL, 0, 0);
857 if (select < max - 1) {
858 PostMessage(parent, CB_SETCURSEL, select + 1, 0);
859 }
860 return 0;
861 case 0x42: // Ctrl+b ... left
862 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
863 PostMessage(dlg, EM_SETSEL, select-1, select-1);
864 return 0;
865 case 0x46: // Ctrl+f ... right
866 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
867 max = GetWindowTextLength(dlg) ;
868 PostMessage(dlg, EM_SETSEL, select+1, select+1);
869 return 0;
870 case 0x41: // Ctrl+a ... home
871 PostMessage(dlg, EM_SETSEL, 0, 0);
872 return 0;
873 case 0x45: // Ctrl+e ... end
874 max = GetWindowTextLength(dlg) ;
875 PostMessage(dlg, EM_SETSEL, max, max);
876 return 0;
877
878 case 0x44: // Ctrl+d
879 case 0x4b: // Ctrl+k
880 case 0x55: // Ctrl+u
881 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
882 max = GetWindowTextLength(dlg);
883 max++; // '\0'
884 orgstr = str = malloc(max);
885 if (str != NULL) {
886 len = GetWindowText(dlg, str, max);
887 if (select >= 0 && select < len) {
888 if (wParam == 0x44) { // �J�[�\���z����������������������
889 memmove(&str[select], &str[select + 1], len - select - 1);
890 str[len - 1] = '\0';
891
892 } else if (wParam == 0x4b) { // �J�[�\�������s��������������
893 str[select] = '\0';
894
895 }
896 }
897
898 if (wParam == 0x55) { // �J�[�\����������������������
899 if (select >= len) {
900 str[0] = '\0';
901 } else {
902 str = &str[select];
903 }
904 select = 0;
905 }
906
907 SetWindowText(dlg, str);
908 SendMessage(dlg, EM_SETSEL, select, select);
909 free(orgstr);
910 return 0;
911 }
912 break;
913 }
914 }
915 break;
916
917 // �����L�[��������������������������������������������
918 case WM_CHAR:
919 switch (wParam) {
920 case 0x01:
921 case 0x02:
922 case 0x04:
923 case 0x05:
924 case 0x06:
925 case 0x0b:
926 case 0x0e:
927 case 0x10:
928 case 0x15:
929 return 0;
930 }
931 }
932
933 return CallWindowProc(OrigHostnameEditProc, dlg, msg, wParam, lParam);
934 }
935
936 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
937 LPARAM lParam)
938 {
939 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
940 PGetHNRec GetHNRec;
941 char EntName[128];
942 char TempHost[HostNameMaxLength + 1];
943 WORD i, j, w;
944 WORD ComPortTable[MAXCOMPORT];
945 static char *ComPortDesc[MAXCOMPORT];
946 int comports;
947 BOOL Ok;
948 LOGFONT logfont;
949 HFONT font;
950 char uimsg[MAX_UIMSG];
951 static HWND hwndHostname = NULL; // HOSTNAME dropdown
952 static HWND hwndHostnameEdit = NULL; // Edit control on HOSTNAME dropdown
953
954 GET_VAR();
955
956 switch (msg) {
957 case WM_INITDIALOG:
958 GetHNRec = (PGetHNRec) lParam;
959 SetWindowLong(dlg, DWL_USER, lParam);
960
961 GetWindowText(dlg, uimsg, sizeof(uimsg));
962 UTIL_get_lang_msg("DLG_HOST_TITLE", pvar, uimsg);
963 SetWindowText(dlg, pvar->ts->UIMsg);
964 GetDlgItemText(dlg, IDC_HOSTNAMELABEL, uimsg, sizeof(uimsg));
965 UTIL_get_lang_msg("DLG_HOST_TCPIPHOST", pvar, uimsg);
966 SetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg);
967 GetDlgItemText(dlg, IDC_HISTORY, uimsg, sizeof(uimsg));
968 UTIL_get_lang_msg("DLG_HOST_TCPIPHISTORY", pvar, uimsg);
969 SetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg);
970 GetDlgItemText(dlg, IDC_SERVICELABEL, uimsg, sizeof(uimsg));
971 UTIL_get_lang_msg("DLG_HOST_TCPIPSERVICE", pvar, uimsg);
972 SetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg);
973 GetDlgItemText(dlg, IDC_HOSTOTHER, uimsg, sizeof(uimsg));
974 UTIL_get_lang_msg("DLG_HOST_TCPIPOTHER", pvar, uimsg);
975 SetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg);
976 GetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, uimsg, sizeof(uimsg));
977 UTIL_get_lang_msg("DLG_HOST_TCPIPPORT", pvar, uimsg);
978 SetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg);
979 GetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, uimsg, sizeof(uimsg));
980 UTIL_get_lang_msg("DLG_HOST_TCPIPSSHVERSION", pvar, uimsg);
981 SetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg);
982 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, uimsg, sizeof(uimsg));
983 UTIL_get_lang_msg("DLG_HOST_TCPIPPROTOCOL", pvar, uimsg);
984 SetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg);
985 GetDlgItemText(dlg, IDC_HOSTSERIAL, uimsg, sizeof(uimsg));
986 UTIL_get_lang_msg("DLG_HOST_SERIAL", pvar, uimsg);
987 SetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg);
988 GetDlgItemText(dlg, IDC_HOSTCOMLABEL, uimsg, sizeof(uimsg));
989 UTIL_get_lang_msg("DLG_HOST_SERIALPORT", pvar, uimsg);
990 SetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg);
991 GetDlgItemText(dlg, IDC_HOSTHELP, uimsg, sizeof(uimsg));
992 UTIL_get_lang_msg("DLG_HOST_HELP", pvar, uimsg);
993 SetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg);
994 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
995 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
996 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
997 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
998 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
999 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1000
1001 // �z�X�g�q�X�g�����`�F�b�N�{�b�N�X������ (2005.10.21 yutaka)
1002 if (pvar->ts->HistoryList > 0) {
1003 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_CHECKED, 0);
1004 } else {
1005 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_UNCHECKED, 0);
1006 }
1007
1008 if (GetHNRec->PortType == IdFile)
1009 GetHNRec->PortType = IdTCPIP;
1010
1011 strncpy_s(EntName, sizeof(EntName), "Host", _TRUNCATE);
1012
1013 i = 1;
1014 do {
1015 _snprintf_s(&EntName[4], sizeof(EntName)-4, _TRUNCATE, "%d", i);
1016 GetPrivateProfileString("Hosts", EntName, "",
1017 TempHost, sizeof(TempHost),
1018 GetHNRec->SetupFN);
1019 if (strlen(TempHost) > 0)
1020 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
1021 0, (LPARAM) TempHost);
1022 i++;
1023 } while ((i <= MAXHOSTLIST) && (strlen(TempHost) > 0));
1024
1025 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
1026 HostNameMaxLength - 1, 0);
1027
1028 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
1029
1030 // C-n/C-p ���������T�u�N���X�� (2007.9.4 maya)
1031 hwndHostname = GetDlgItem(dlg, IDC_HOSTNAME);
1032 hwndHostnameEdit = GetWindow(hwndHostname, GW_CHILD);
1033 OrigHostnameEditProc = (WNDPROC)GetWindowLong(hwndHostnameEdit, GWL_WNDPROC);
1034 SetWindowLong(hwndHostnameEdit, GWL_WNDPROC, (LONG)HostnameEditProc);
1035
1036 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
1037 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
1038 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
1039 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
1040 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
1041 #ifndef NO_INET6
1042 for (i = 0; ProtocolFamilyList[i]; ++i) {
1043 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
1044 0, (LPARAM) ProtocolFamilyList[i]);
1045 }
1046 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
1047 ProtocolFamilyMaxLength - 1, 0);
1048 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
1049 #endif /* NO_INET6 */
1050
1051 /////// SSH version
1052 for (i = 0; ssh_version[i]; ++i) {
1053 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
1054 0, (LPARAM) ssh_version[i]);
1055 }
1056 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
1057 NUM_ELEM(ssh_version) - 1, 0);
1058
1059 if (pvar->settings.ssh_protocol_version == 1) {
1060 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
1061 } else {
1062 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
1063 }
1064
1065 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1066 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
1067 } else {
1068 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1069 }
1070 /////// SSH version
1071
1072
1073 j = 0;
1074 w = 1;
1075 if ((comports=DetectComPorts(ComPortTable, GetHNRec->MaxComPort, ComPortDesc)) >= 0) {
1076 for (i=0; i<comports; i++) {
1077 // MaxComPort ���z�����|�[�g���\��������
1078 if (ComPortTable[i] > GetHNRec->MaxComPort) {
1079 continue;
1080 }
1081
1082 // �g�p�����|�[�g���\��������
1083 if (CheckCOMFlag(ComPortTable[i]) == 1) {
1084 continue;
1085 }
1086
1087 _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "COM%d", ComPortTable[i]);
1088 if (ComPortDesc[i] != NULL) {
1089 strncat_s(EntName, sizeof(EntName), ": ", _TRUNCATE);
1090 strncat_s(EntName, sizeof(EntName), ComPortDesc[i], _TRUNCATE);
1091 }
1092 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1093 0, (LPARAM)EntName);
1094 j++;
1095 if (GetHNRec->ComPort == ComPortTable[i])
1096 w = j;
1097 }
1098
1099 } else {
1100 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
1101 // �g�p�����|�[�g���\��������
1102 if (CheckCOMFlag(i) == 1) {
1103 continue;
1104 }
1105
1106 _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "COM%d", i);
1107 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1108 0, (LPARAM) EntName);
1109 j++;
1110 if (GetHNRec->ComPort == i)
1111 w = j;
1112 }
1113 }
1114
1115 if (j > 0)
1116 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
1117 else { /* All com ports are already used */
1118 GetHNRec->PortType = IdTCPIP;
1119 enable_dlg_items(dlg, IDC_HOSTSERIAL, IDC_HOSTSERIAL, FALSE);
1120 }
1121
1122 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
1123 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
1124
1125 if (GetHNRec->PortType == IdTCPIP) {
1126 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1127
1128 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1129 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE);
1130
1131 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // enabled
1132 }
1133 #ifndef NO_INET6
1134 else {
1135 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1136 FALSE);
1137 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1138 IDC_HOSTTCPPROTOCOL, FALSE);
1139
1140 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1141 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1142
1143 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1144 }
1145 #else
1146 else
1147 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1148 FALSE);
1149 #endif /* NO_INET6 */
1150
1151 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
1152 if (GetHNRec->PortType == IdTCPIP) {
1153 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
1154 SetFocus(hwnd);
1155 } else {
1156 HWND hwnd = GetDlgItem(dlg, IDC_HOSTCOM);
1157 SetFocus(hwnd);
1158 }
1159
1160 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1161 GetObject(font, sizeof(LOGFONT), &logfont);
1162 if (UTIL_get_lang_font("DLG_SYSTEM_FONT", dlg, &logfont, &DlgHostFont, pvar)) {
1163 SendDlgItemMessage(dlg, IDC_HOSTTCPIP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1164 SendDlgItemMessage(dlg, IDC_HOSTNAMELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1165 SendDlgItemMessage(dlg, IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1166 SendDlgItemMessage(dlg, IDC_HISTORY, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1167 SendDlgItemMessage(dlg, IDC_SERVICELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1168 SendDlgItemMessage(dlg, IDC_HOSTTELNET, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1169 SendDlgItemMessage(dlg, IDC_HOSTSSH, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1170 SendDlgItemMessage(dlg, IDC_HOSTOTHER, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1171 SendDlgItemMessage(dlg, IDC_HOSTTCPPORTLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1172 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1173 SendDlgItemMessage(dlg, IDC_SSH_VERSION_LABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1174 SendDlgItemMessage(dlg, IDC_SSH_VERSION, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1175 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOLLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1176 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1177 SendDlgItemMessage(dlg, IDC_HOSTSERIAL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1178 SendDlgItemMessage(dlg, IDC_HOSTCOMLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1179 SendDlgItemMessage(dlg, IDC_HOSTCOM, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1180 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1181 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1182 SendDlgItemMessage(dlg, IDC_HOSTHELP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1183 }
1184 else {
1185 DlgHostFont = NULL;
1186 }
1187
1188 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
1189 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
1190 // (2004.11.23 yutaka)
1191 return FALSE;
1192 //return TRUE;
1193
1194 case WM_COMMAND:
1195 switch (LOWORD(wParam)) {
1196 case IDOK:
1197 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1198 if (GetHNRec != NULL) {
1199 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
1200 #ifndef NO_INET6
1201 char afstr[BUFSIZ];
1202 #endif /* NO_INET6 */
1203 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
1204 if (Ok) {
1205 GetHNRec->TCPPort = i;
1206 } else {
1207 UTIL_get_lang_msg("MSG_TCPPORT_NAN_ERROR", pvar,
1208 "The TCP port must be a number.");
1209 MessageBox(dlg, pvar->ts->UIMsg,
1210 "Tera Term", MB_OK | MB_ICONEXCLAMATION);
1211 return TRUE;
1212 }
1213 #ifndef NO_INET6
1214 #define getaf(str) \
1215 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
1216 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
1217 memset(afstr, 0, sizeof(afstr));
1218 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
1219 sizeof(afstr));
1220 GetHNRec->ProtocolFamily = getaf(afstr);
1221 #endif /* NO_INET6 */
1222 GetHNRec->PortType = IdTCPIP;
1223 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
1224 HostNameMaxLength);
1225 GetHNRec->Telnet = FALSE;
1226 pvar->hostdlg_activated = TRUE;
1227 pvar->hostdlg_Enabled = FALSE;
1228 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1229 GetHNRec->Telnet = TRUE;
1230 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1231 pvar->hostdlg_Enabled = TRUE;
1232
1233 // check SSH protocol version
1234 memset(afstr, 0, sizeof(afstr));
1235 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
1236 if (_stricmp(afstr, "SSH1") == 0) {
1237 pvar->settings.ssh_protocol_version = 1;
1238 } else {
1239 pvar->settings.ssh_protocol_version = 2;
1240 }
1241 }
1242
1243 // host history check button
1244 if (SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_GETCHECK, 0, 0) == BST_CHECKED) {
1245 pvar->ts->HistoryList = 1;
1246 } else {
1247 pvar->ts->HistoryList = 0;
1248 }
1249
1250 } else {
1251 GetHNRec->PortType = IdSerial;
1252 GetHNRec->HostName[0] = 0;
1253 memset(EntName, 0, sizeof(EntName));
1254 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1255 sizeof(EntName) - 1);
1256 if (strncmp(EntName, "COM", 3) == 0 && EntName[3] != '\0') {
1257 #if 0
1258 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
1259 if (strlen(EntName) > 4)
1260 GetHNRec->ComPort =
1261 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
1262 0x30;
1263 #else
1264 GetHNRec->ComPort = atoi(&EntName[3]);
1265 #endif
1266 if (GetHNRec->ComPort > GetHNRec->MaxComPort)
1267 GetHNRec->ComPort = 1;
1268 } else {
1269 GetHNRec->ComPort = 1;
1270 }
1271 }
1272 }
1273 SetWindowLong(hwndHostnameEdit, GWL_WNDPROC, (LONG)OrigHostnameEditProc);
1274 EndDialog(dlg, 1);
1275
1276 if (DlgHostFont != NULL) {
1277 DeleteObject(DlgHostFont);
1278 }
1279
1280 return TRUE;
1281
1282 case IDCANCEL:
1283 SetWindowLong(hwndHostnameEdit, GWL_WNDPROC, (LONG)OrigHostnameEditProc);
1284 EndDialog(dlg, 0);
1285
1286 if (DlgHostFont != NULL) {
1287 DeleteObject(DlgHostFont);
1288 }
1289
1290 return TRUE;
1291
1292 case IDC_HOSTTCPIP:
1293 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1294 TRUE);
1295 #ifndef NO_INET6
1296 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1297 IDC_HOSTTCPPROTOCOL, TRUE);
1298 #endif /* NO_INET6 */
1299 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1300
1301 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1302 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1303 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1304 } else {
1305 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1306 }
1307
1308 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // disabled
1309
1310 return TRUE;
1311
1312 case IDC_HOSTSERIAL:
1313 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1314 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1315 FALSE);
1316 #ifndef NO_INET6
1317 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1318 IDC_HOSTTCPPROTOCOL, FALSE);
1319 #endif /* NO_INET6 */
1320 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1321 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1322
1323 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1324
1325 return TRUE;
1326
1327 case IDC_HOSTSSH:
1328 enable_dlg_items(dlg, IDC_SSH_VERSION,
1329 IDC_SSH_VERSION, TRUE);
1330 goto hostssh_enabled;
1331
1332 case IDC_HOSTTELNET:
1333 case IDC_HOSTOTHER:
1334 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1335 hostssh_enabled:
1336
1337 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1338
1339 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1340 if (GetHNRec != NULL)
1341 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1342 FALSE);
1343 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1344 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1345 }
1346 return TRUE;
1347
1348 case IDC_HOSTCOM:
1349 if(HIWORD(wParam) == CBN_DROPDOWN) {
1350 HWND hostcom = GetDlgItem(dlg, IDC_HOSTCOM);
1351 int count = SendMessage(hostcom, CB_GETCOUNT, 0, 0);
1352 int i, len, max_len = 0;
1353 char *lbl;
1354 HDC TmpDC = GetDC(hostcom);
1355 SIZE s;
1356 for (i=0; i<count; i++) {
1357 len = SendMessage(hostcom, CB_GETLBTEXTLEN, i, 0);
1358 lbl = (char *)calloc(len+1, sizeof(char));
1359 SendMessage(hostcom, CB_GETLBTEXT, i, (LPARAM)lbl);
1360 GetTextExtentPoint32(TmpDC, lbl, len, &s);
1361 if (s.cx > max_len)
1362 max_len = s.cx;
1363 free(lbl);
1364 }
1365 SendMessage(hostcom, CB_SETDROPPEDWIDTH,
1366 max_len + GetSystemMetrics(SM_CXVSCROLL), 0);
1367 }
1368 break;
1369
1370 case IDC_HOSTHELP:
1371 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1372 }
1373 }
1374 return FALSE;
1375 }
1376
1377 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1378 {
1379 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1380 parent, TTXHostDlg, (LONG) rec);
1381 }
1382
1383 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1384 {
1385 GET_VAR();
1386
1387 *hooks->GetHostName = TTXGetHostName;
1388 }
1389
1390 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1391 {
1392 GET_VAR();
1393
1394 (pvar->ReadIniFile) (fileName, ts);
1395 read_ssh_options(pvar, fileName);
1396 pvar->settings = *pvar->ts_SSH;
1397 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1398 FWDUI_load_settings(pvar);
1399 }
1400
1401 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1402 {
1403 GET_VAR();
1404
1405 (pvar->WriteIniFile) (fileName, ts);
1406 *pvar->ts_SSH = pvar->settings;
1407 clear_local_settings(pvar);
1408 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1409 write_ssh_options(pvar, fileName, pvar->ts_SSH, TRUE);
1410 }
1411
1412 static void read_ssh_options_from_user_file(PTInstVar pvar,
1413 char FAR * user_file_name)
1414 {
1415 if (user_file_name[0] == '.') {
1416 read_ssh_options(pvar, user_file_name);
1417 } else {
1418 char buf[1024];
1419
1420 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1421 read_ssh_options(pvar, buf);
1422 }
1423
1424 pvar->settings = *pvar->ts_SSH;
1425 FWDUI_load_settings(pvar);
1426 }
1427
1428
1429 // @���u�����N���u�������B (2005.1.26 yutaka)
1430 static void replace_to_blank(char *src, char *dst, int dst_len)
1431 {
1432 int len, i;
1433
1434 len = strlen(src);
1435 if (dst_len < len) // buffer overflow check
1436 return;
1437
1438 for (i = 0 ; i < len ; i++) {
1439 if (src[i] == '@') { // @ ���o��������
1440 if (i < len - 1 && src[i + 1] == '@') { // �������� @ �����A�b�g�}�[�N���F������
1441 *dst++ = '@';
1442 i++;
1443 } else {
1444 *dst++ = ' '; // �������u��������
1445 }
1446 } else {
1447 *dst++ = src[i];
1448 }
1449 }
1450 *dst = '\0';
1451 }
1452
1453 /* returns 1 if the option text must be deleted */
1454 static int parse_option(PTInstVar pvar, char FAR * option)
1455 {
1456 if ((option[0] == '-' || option[0] == '/')) {
1457 if (MATCH_STR(option + 1, "ssh") == 0) {
1458 if (option[4] == 0) {
1459 pvar->settings.Enabled = 1;
1460 } else if (MATCH_STR(option + 4, "-L") == 0 ||
1461 MATCH_STR(option + 4, "-R") == 0 ||
1462 _stricmp(option + 4, "-X") == 0) {
1463 if (pvar->settings.DefaultForwarding[0] == 0) {
1464 strncpy_s(pvar->settings.DefaultForwarding,
1465 sizeof(pvar->settings.DefaultForwarding),
1466 option + 5, _TRUNCATE);
1467 } else {
1468 strncat_s(pvar->settings.DefaultForwarding,
1469 sizeof(pvar->settings.DefaultForwarding),
1470 ";", _TRUNCATE);
1471 strncat_s(pvar->settings.DefaultForwarding,
1472 sizeof(pvar->settings.DefaultForwarding),
1473 option + 5, _TRUNCATE);
1474 }
1475 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1476 read_ssh_options_from_user_file(pvar, option + 7);
1477 } else if (MATCH_STR(option + 4, "-v") == 0) {
1478 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1479 } else if (_stricmp(option + 4, "-autologin") == 0 ||
1480 _stricmp(option + 4, "-autologon") == 0) {
1481 pvar->settings.TryDefaultAuth = TRUE;
1482
1483 } else if (_stricmp(option + 4, "-acceptall") == 0) {
1484 pvar->settings.LocalForwardingIdentityCheck = FALSE;
1485
1486 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1487 read_ssh_options_from_user_file(pvar, option + 13);
1488 DeleteFile(option + 13);
1489
1490 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1491 } else if (MATCH_STR(option + 4, "1") == 0) {
1492 pvar->settings.Enabled = 1;
1493 pvar->settings.ssh_protocol_version = 1;
1494 } else if (MATCH_STR(option + 4, "2") == 0) {
1495 pvar->settings.Enabled = 1;
1496 pvar->settings.ssh_protocol_version = 2;
1497
1498 } else {
1499 char buf[1024];
1500
1501 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar,
1502 "Unrecognized command-line option: %s");
1503 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, option);
1504
1505 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1506 }
1507
1508 return 1;
1509
1510 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1511 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1512 if (strcmp(option + 3, "2") == 0) {
1513 pvar->settings.Enabled = 1;
1514 return 1;
1515 } else {
1516 pvar->settings.Enabled = 0;
1517 }
1518
1519 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1520 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1521 read_ssh_options_from_user_file(pvar, option + 3);
1522
1523 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1524 } else if (MATCH_STR(option + 1, "1") == 0) {
1525 // command line: /ssh /1 is SSH1 only
1526 pvar->settings.ssh_protocol_version = 1;
1527
1528 } else if (MATCH_STR(option + 1, "2") == 0) {
1529 // command line: /ssh /2 is SSH2 & SSH1
1530 pvar->settings.ssh_protocol_version = 2;
1531
1532 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1533 // '/nossh' �I�v�V�����������B
1534 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1535 // �����������������B(2004.10.11 yutaka)
1536 pvar->settings.Enabled = 0;
1537
1538 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1539 // '/telnet' ���w�������������������� '/nossh' ��������
1540 // SSH������������ (2006.9.16 maya)
1541 pvar->settings.Enabled = 0;
1542
1543 } else if (MATCH_STR(option + 1, "auth") == 0) {
1544 // SSH2�������O�C���I�v�V����������
1545 //
1546 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1547 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1548 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1549 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1550 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1551 //
1552 // (2004.11.30 yutaka)
1553 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1554 //
1555 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1556
1557 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h
1558 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1559 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1560
1561 // /auth=challenge ������ (2007.10.5 maya)
1562 } else if (MATCH_STR(option + 5, "=challenge") == 0) { // keyboard-interactive�F��
1563 //pvar->auth_state.cur_cred.method = SSH_AUTH_TIS;
1564 pvar->ssh2_authmethod = SSH_AUTH_TIS;
1565
1566 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1567 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1568 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1569
1570 } else if (MATCH_STR(option + 5, "=pageant") == 0) { // ���J���F�� by Pageant
1571 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1572 pvar->ssh2_authmethod = SSH_AUTH_PAGEANT;
1573
1574 } else {
1575 // TODO:
1576
1577 }
1578
1579 } else if (MATCH_STR(option + 1, "user=") == 0) {
1580 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1581 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1582
1583 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1584 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1585 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1586
1587 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1588 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1589
1590 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1591 // �p�X���[�h������ (2006.9.18 maya)
1592 pvar->ask4passwd = 1;
1593
1594 }
1595
1596 // �p�X���[�h�������������������O�C��������������
1597 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1598 if (pvar->ask4passwd == 1) {
1599 pvar->ssh2_autologin = 0;
1600 }
1601
1602 }
1603
1604 return 0;
1605 }
1606
1607 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1608 PCHAR DDETopic)
1609 {
1610 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1611 int i;
1612 BOOL inParam = FALSE;
1613 BOOL inQuotes = FALSE;
1614 BOOL inFileParam = FALSE;
1615 PCHAR option = NULL;
1616 GET_VAR();
1617
1618 if (pvar->hostdlg_activated) {
1619 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1620 }
1621
1622 for (i = 0; param[i] != 0; i++) {
1623 if (inQuotes ? param[i] == '"'
1624 : (param[i] == ' ' || param[i] == '\t')) {
1625 if (option != NULL) {
1626 char ch = param[i];
1627 PCHAR Equal;
1628
1629 param[i] = 0;
1630 Equal = strchr(option, '=');
1631 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1632 int buf_len = strlen(option) * sizeof(char);
1633 char *buf = (char *)calloc(strlen(option), sizeof(char));
1634 char c = option[Equal - option + 1];
1635 option[Equal - option + 1] = 0;
1636 strncat_s(buf, buf_len, option, _TRUNCATE);
1637 option[Equal - option + 1] = c;
1638 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1639 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1640 memset(option, ' ', i + 1 - (option - param));
1641 } else {
1642 param[i] = ch;
1643 }
1644 free(buf);
1645 }
1646 else {
1647 if (parse_option(pvar, *option == '"' ? option + 1 : option)) {
1648 memset(option, ' ', i + 1 - (option - param));
1649 } else {
1650 param[i] = ch;
1651 }
1652 }
1653 option = NULL;
1654 }
1655 inParam = FALSE;
1656 inQuotes = FALSE;
1657 inFileParam = FALSE;
1658 } else if (!inParam) {
1659 if (param[i] == '"') {
1660 inQuotes = TRUE;
1661 inParam = TRUE;
1662 option = param + i;
1663 } else if (param[i] != ' ' && param[i] != '\t') {
1664 inParam = TRUE;
1665 option = param + i;
1666 }
1667 } else {
1668 if (option == NULL) {
1669 continue;
1670 }
1671 if ((option[0] == '-' || option[0] == '/') &&
1672 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1673 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1674 MATCH_STR_I(option + 1, "f=") == 0 ||
1675 MATCH_STR(option + 1, "keyfile=") == 0)) {
1676 if (param[i] == '"') {
1677 inQuotes = TRUE;
1678 }
1679 inFileParam = TRUE;
1680 }
1681 }
1682 }
1683
1684 if (option != NULL) {
1685 PCHAR Equal = strchr(option, '=');
1686 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1687 int buf_len = strlen(option) * sizeof(char);
1688 char *buf = (char *)calloc(strlen(option), sizeof(char));
1689 char c = option[Equal - option + 1];
1690 option[Equal - option + 1] = 0;
1691 strncat_s(buf, buf_len, option, _TRUNCATE);
1692 option[Equal - option + 1] = c;
1693 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1694 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1695 memset(option, ' ', i + 1 - (option - param));
1696 }
1697 free(buf);
1698 }
1699 else {
1700 if (parse_option(pvar, option)) {
1701 memset(option, ' ', i - (option - param));
1702 }
1703 }
1704 }
1705
1706 FWDUI_load_settings(pvar);
1707
1708 (pvar->ParseParam) (param, ts, DDETopic);
1709
1710 }
1711
1712 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1713 {
1714 GET_VAR();
1715
1716 pvar->ReadIniFile = *hooks->ReadIniFile;
1717 pvar->WriteIniFile = *hooks->WriteIniFile;
1718 pvar->ParseParam = *hooks->ParseParam;
1719
1720 *hooks->ReadIniFile = TTXReadINIFile;
1721 *hooks->WriteIniFile = TTXWriteINIFile;
1722 *hooks->ParseParam = TTXParseParam;
1723 }
1724
1725 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1726 {
1727 GET_VAR();
1728
1729 SSH_notify_win_size(pvar, cols, rows);
1730 }
1731
1732 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1733 WORD newItemID, char FAR * text)
1734 {
1735 int i, j;
1736
1737 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1738 HMENU submenu = GetSubMenu(menu, i);
1739
1740 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1741 if (GetMenuItemID(submenu, j) == beforeItemID) {
1742 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID, text);
1743 return;
1744 }
1745 }
1746 }
1747 }
1748
1749 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1750 {
1751 GET_VAR();
1752
1753 /* inserts before ID_HELP_ABOUT */
1754 UTIL_get_lang_msg("MENU_ABOUT", pvar, "About &TTSSH...");
1755 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1756
1757 /* inserts before ID_SETUP_TCPIP */
1758 UTIL_get_lang_msg("MENU_SSH", pvar, "SS&H...");
1759 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1760 /* inserts before ID_SETUP_TCPIP */
1761 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar, "SSH &Authentication...");
1762 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1763 /* inserts before ID_SETUP_TCPIP */
1764 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar, "SSH F&orwarding...");
1765 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1766 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar, "SSH KeyGe&nerator...");
1767 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1768
1769 /* inserts before ID_FILE_CHANGEDIR */
1770 UTIL_get_lang_msg("MENU_SSH_SCP", pvar, "SSH SCP...");
1771 insertMenuBeforeItem(menu, 50170, MF_ENABLED, ID_SSHSCPMENU, pvar->ts->UIMsg);
1772 }
1773
1774 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1775 {
1776 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1777 (LPARAM) prefix);
1778 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1779 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1780 (LPARAM) (char FAR *) "\r\n");
1781 }
1782
1783 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1784 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1785 {
1786 typedef struct {
1787 WORD wLanguage;
1788 WORD wCodePage;
1789 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1790 LPLANGANDCODEPAGE lplgcode;
1791 UINT unLen;
1792 DWORD size;
1793 char *buf = NULL;
1794 BOOL ret;
1795 int i;
1796 char fmt[80];
1797 char *pbuf;
1798
1799 size = GetFileVersionInfoSize(exefile, NULL);
1800 if (size == 0) {
1801 goto error;
1802 }
1803 buf = malloc(size);
1804 ZeroMemory(buf, size);
1805
1806 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1807 goto error;
1808 }
1809
1810 ret = VerQueryValue(buf,
1811 "\\VarFileInfo\\Translation",
1812 (LPVOID *)&lplgcode, &unLen);
1813 if (ret == FALSE)
1814 goto error;
1815
1816 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1817 _snprintf_s(fmt, sizeof(fmt), _TRUNCATE,
1818 "\\StringFileInfo\\%04x%04x\\FileVersion",
1819 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1820 VerQueryValue(buf, fmt, &pbuf, &unLen);
1821 if (unLen > 0) { // get success
1822 int n, a, b, c, d;
1823
1824 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1825 if (n == 4) { // convert success
1826 *major = a;
1827 *minor = b;
1828 *release = c;
1829 *build = d;
1830 break;
1831 }
1832 }
1833 }
1834
1835 free(buf);
1836 return;
1837
1838 error:
1839 free(buf);
1840 *major = *minor = *release = *build = 0;
1841 }
1842
1843 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1844 {
1845 char buf[1024];
1846 int a, b, c, d;
1847 char uimsg[MAX_UIMSG];
1848
1849 GetWindowText(dlg, uimsg, sizeof(uimsg));
1850 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar, uimsg);
1851 SetWindowText(dlg, pvar->ts->UIMsg);
1852 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
1853 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
1854 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1855
1856 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1857 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1858 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1859 "TTSSH\r\nTera Term Secure Shell extension, %d.%d", a, b);
1860 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1861
1862 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1863 // ���������� (2005.5.11 yutaka)
1864 #ifdef OPENSSL_VERSION_TEXT
1865 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1866 #else
1867 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1868 #endif
1869
1870 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1871 #ifdef ZLIB_VERSION
1872 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "ZLib %s", ZLIB_VERSION);
1873 #else
1874 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1875 #endif
1876 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1877
1878
1879 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1880 if (pvar->socket != INVALID_SOCKET) {
1881 if (SSHv1(pvar)) {
1882 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1883 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1884 append_about_text(dlg, pvar->ts->UIMsg, buf);
1885 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1886 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1887 append_about_text(dlg, pvar->ts->UIMsg, buf);
1888 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1889 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1890 append_about_text(dlg, pvar->ts->UIMsg, buf);
1891 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1892 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1893 append_about_text(dlg, pvar->ts->UIMsg, buf);
1894 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1895 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1896 append_about_text(dlg, pvar->ts->UIMsg, buf);
1897 SSH_get_compression_info(pvar, buf, sizeof(buf));
1898 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1899 append_about_text(dlg, pvar->ts->UIMsg, buf);
1900
1901 } else { // SSH2
1902 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1903 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1904 append_about_text(dlg, pvar->ts->UIMsg, buf);
1905 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar, "Client ID: ");
1906 append_about_text(dlg, pvar->ts->UIMsg, pvar->client_version_string);
1907
1908 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1909 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1910 append_about_text(dlg, pvar->ts->UIMsg, buf);
1911
1912 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1913 strncpy_s(buf, sizeof(buf), KEX_DH1, _TRUNCATE);
1914 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1915 strncpy_s(buf, sizeof(buf), KEX_DH14, _TRUNCATE);
1916 } else {
1917 strncpy_s(buf, sizeof(buf), KEX_DHGEX, _TRUNCATE);
1918 }
1919 append_about_text(dlg, "KEX: ", buf);
1920
1921 if (pvar->hostkey_type == KEY_DSA) {
1922 strncpy_s(buf, sizeof(buf), "ssh-dss", _TRUNCATE);
1923 } else {
1924 strncpy_s(buf, sizeof(buf), "ssh-rsa", _TRUNCATE);
1925 }
1926 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar, "Host Key: ");
1927 append_about_text(dlg, pvar->ts->UIMsg, buf);
1928
1929 // add HMAC algorithm (2004.12.17 yutaka)
1930 buf[0] = '\0';
1931 if (pvar->ctos_hmac == HMAC_SHA1) {
1932 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1933 } else if (pvar->ctos_hmac == HMAC_MD5) {
1934 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1935 }
1936 UTIL_get_lang_msg("DLG_ABOUT_TOSERVER", pvar, " to server, ");
1937 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1938 if (pvar->stoc_hmac == HMAC_SHA1) {
1939 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1940 } else if (pvar->stoc_hmac == HMAC_MD5) {
1941 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1942 }
1943 UTIL_get_lang_msg("DLG_ABOUT_FROMSERVER", pvar, " from server");
1944 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1945 append_about_text(dlg, "HMAC: ", buf);
1946
1947 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1948 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1949 append_about_text(dlg, pvar->ts->UIMsg, buf);
1950 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1951 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1952 append_about_text(dlg, pvar->ts->UIMsg, buf);
1953
1954 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1955 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1956 append_about_text(dlg, pvar->ts->UIMsg, buf);
1957
1958 SSH_get_compression_info(pvar, buf, sizeof(buf));
1959 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1960 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar, "Delayed Compression: ");
1961 append_about_text(dlg, pvar->ts->UIMsg, buf);
1962 } else {
1963 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1964 append_about_text(dlg, pvar->ts->UIMsg, buf);
1965 }
1966 }
1967 }
1968 }
1969
1970 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1971 LPARAM lParam)
1972 {
1973 LOGFONT logfont;
1974 HFONT font;
1975
1976 switch (msg) {
1977 case WM_INITDIALOG:
1978 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1979 GetObject(font, sizeof(LOGFONT), &logfont);
1980 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
1981 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1982 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1983 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1984 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1985 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1986 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1987 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1988 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1989 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1990 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1991 }
1992 else {
1993 DlgAboutFont = NULL;
1994 }
1995
1996 // �A�C�R�������I���Z�b�g
1997 {
1998 int fuLoad = LR_DEFAULTCOLOR;
1999 HICON hicon;
2000
2001 if (is_NT4()) {
2002 fuLoad = LR_VGACOLOR;
2003 }
2004
2005 hicon = LoadImage(hInst, MAKEINTRESOURCE(IDI_SECURETT),
2006 IMAGE_ICON, 32, 32, fuLoad);
2007 SendDlgItemMessage(dlg, IDC_TTSSH_ICON, STM_SETICON, (WPARAM)hicon, 0);
2008 }
2009
2010 init_about_dlg((PTInstVar) lParam, dlg);
2011 return TRUE;
2012 case WM_COMMAND:
2013 switch (LOWORD(wParam)) {
2014 case IDOK:
2015 EndDialog(dlg, 1);
2016 if (DlgAboutFont != NULL) {
2017 DeleteObject(DlgAboutFont);
2018 }
2019 return TRUE;
2020 case IDCANCEL: /* there isn't a cancel button, but other Windows
2021 UI things can send this message */
2022 EndDialog(dlg, 0);
2023 if (DlgAboutFont != NULL) {
2024 DeleteObject(DlgAboutFont);
2025 }
2026 return TRUE;
2027 }
2028 break;
2029 }
2030
2031 return FALSE;
2032 }
2033
2034 static char FAR *get_cipher_name(int cipher)
2035 {
2036 switch (cipher) {
2037 case SSH_CIPHER_NONE:
2038 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
2039 "<ciphers below this line are disabled>");
2040 return pvar->ts->UIMsg;
2041 case SSH_CIPHER_RC4:
2042 return "RC4(SSH1)";
2043 case SSH_CIPHER_3DES:
2044 return "3DES(SSH1)";
2045 case SSH_CIPHER_DES:
2046 return "DES(SSH1)";
2047 case SSH_CIPHER_IDEA:
2048 return "IDEA(SSH1)";
2049 case SSH_CIPHER_TSS:
2050 return "TSS(SSH1)";
2051 case SSH_CIPHER_BLOWFISH:
2052 return "Blowfish(SSH1)";
2053
2054 // for SSH2(yutaka)
2055 case SSH2_CIPHER_AES128_CBC:
2056 return "AES128-CBC(SSH2)";
2057 case SSH2_CIPHER_AES192_CBC:
2058 return "AES192-CBC(SSH2)";
2059 case SSH2_CIPHER_AES256_CBC:
2060 return "AES256-CBC(SSH2)";
2061 case SSH2_CIPHER_3DES_CBC:
2062 return "3DES-CBC(SSH2)";
2063 case SSH2_CIPHER_BLOWFISH_CBC:
2064 return "Blowfish-CBC(SSH2)";
2065 case SSH2_CIPHER_AES128_CTR:
2066 return "AES128-CTR(SSH2)";
2067 case SSH2_CIPHER_AES192_CTR:
2068 return "AES192-CTR(SSH2)";
2069 case SSH2_CIPHER_AES256_CTR:
2070 return "AES256-CTR(SSH2)";
2071
2072 default:
2073 return NULL;
2074 }
2075 }
2076
2077 static void set_move_button_status(HWND dlg)
2078 {
2079 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2080 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
2081 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
2082
2083 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP),
2084 curPos > 0 && curPos <= maxPos);
2085 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN),
2086 curPos >= 0 && curPos < maxPos);
2087 }
2088
2089 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
2090 {
2091 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2092 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2093 int i;
2094 int ch;
2095 char uimsg[MAX_UIMSG];
2096
2097 GetWindowText(dlg, uimsg, sizeof(uimsg));
2098 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar, uimsg);
2099 SetWindowText(dlg, pvar->ts->UIMsg);
2100 GetDlgItemText(dlg, IDC_COMPRESSLABEL, uimsg, sizeof(uimsg));
2101 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar, uimsg);
2102 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
2103 GetDlgItemText(dlg, IDC_COMPRESSNONE, uimsg, sizeof(uimsg));
2104 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar, uimsg);
2105 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
2106 GetDlgItemText(dlg, IDC_COMPRESSHIGH, uimsg, sizeof(uimsg));
2107 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar, uimsg);
2108 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
2109 GetDlgItemText(dlg, IDC_CIPHERORDER, uimsg, sizeof(uimsg));
2110 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar, uimsg);
2111 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
2112 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, uimsg, sizeof(uimsg));
2113 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar, uimsg);
2114 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
2115 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, uimsg, sizeof(uimsg));
2116 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar, uimsg);
2117 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
2118 GetDlgItemText(dlg, IDC_KNOWNHOSTS, uimsg, sizeof(uimsg));
2119 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar, uimsg);
2120 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
2121 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, uimsg, sizeof(uimsg));
2122 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar, uimsg);
2123 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
2124 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, uimsg, sizeof(uimsg));
2125 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar, uimsg);
2126 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
2127 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, uimsg, sizeof(uimsg));
2128 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar, uimsg);
2129 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
2130 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, uimsg, sizeof(uimsg));
2131 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar, uimsg);
2132 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
2133 GetDlgItemText(dlg, IDC_NOTICEBANNER, uimsg, sizeof(uimsg));
2134 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar, uimsg);
2135 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
2136 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2137 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
2138 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2139 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2140 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
2141 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2142
2143 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2144 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2145 pvar->settings.CompressionLevel);
2146
2147 normalize_cipher_order(pvar->settings.CipherOrder);
2148
2149 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2150 int cipher = pvar->settings.CipherOrder[i] - '0';
2151 char FAR *name = get_cipher_name(cipher);
2152
2153 if (name != NULL) {
2154 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2155 }
2156 }
2157
2158 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2159 set_move_button_status(dlg);
2160
2161 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2162 i++) {
2163 }
2164 if (ch != 0) {
2165 pvar->settings.KnownHostsFiles[i] = 0;
2166 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2167 pvar->settings.KnownHostsFiles);
2168 pvar->settings.KnownHostsFiles[i] = ch;
2169 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2170 pvar->settings.KnownHostsFiles + i + 1);
2171 } else {
2172 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2173 pvar->settings.KnownHostsFiles);
2174 }
2175
2176 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2177 {
2178 char buf[10];
2179 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2180 "%d", pvar->settings.ssh_heartbeat_overtime);
2181 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2182 }
2183
2184 }
2185
2186 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
2187 char FAR * basename)
2188 {
2189 int filename_start = 0;
2190 int i;
2191 int ch;
2192
2193 if (basename[0] == '\\' || basename[0] == '/'
2194 || (basename[0] != 0 && basename[1] == ':')) {
2195 strncpy_s(buf, bufsize, basename, _TRUNCATE);
2196 return;
2197 }
2198
2199 GetModuleFileName(NULL, buf, bufsize);
2200 for (i = 0; (ch = buf[i]) != 0; i++) {
2201 if (ch == '\\' || ch == '/' || ch == ':') {
2202 filename_start = i + 1;
2203 }
2204 }
2205
2206 if (bufsize > filename_start) {
2207 strncpy_s(buf + filename_start, bufsize - filename_start, basename, _TRUNCATE);
2208 }
2209 }
2210
2211 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
2212 char FAR * basename)
2213 {
2214 char buf[1024];
2215 int filename_start = 0;
2216 int i;
2217 int ch, ch2;
2218
2219 if (basename[0] != '\\' && basename[0] != '/'
2220 && (basename[0] == 0 || basename[1] != ':')) {
2221 strncpy_s(dest, destsize, basename, _TRUNCATE);
2222 return strlen(dest);
2223 }
2224
2225 GetModuleFileName(NULL, buf, sizeof(buf));
2226 for (i = 0; (ch = buf[i]) != 0; i++) {
2227 if (ch == '\\' || ch == '/' || ch == ':') {
2228 filename_start = i + 1;
2229 }
2230 }
2231
2232 for (i = 0; i < filename_start; i++) {
2233 ch = toupper(buf[i]);
2234 ch2 = toupper(basename[i]);
2235
2236 if (ch == ch2 ||
2237 ((ch == '\\' || ch == '/') && (ch2 == '\\' || ch2 == '/'))) {
2238 } else {
2239 break;
2240 }
2241 }
2242
2243 if (i == filename_start) {
2244 strncpy_s(dest, destsize, basename + i, _TRUNCATE);
2245 } else {
2246 strncpy_s(dest, destsize, basename, _TRUNCATE);
2247 }
2248 return strlen(dest);
2249 }
2250
2251 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2252 {
2253 char buf[4096];
2254 char buf2[1024];
2255 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2256 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2257 int i, j, buf2index, bufindex;
2258 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2259
2260 pvar->settings.CompressionLevel =
2261 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2262
2263 buf2index = 0;
2264 for (i = 0; i < count; i++) {
2265 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2266
2267 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2268 buf[0] = 0;
2269 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2270 for (j = 0;
2271 j <= SSH_CIPHER_MAX
2272 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2273 }
2274 if (j <= SSH_CIPHER_MAX) {
2275 buf2[buf2index] = '0' + j;
2276 buf2index++;
2277 }
2278 }
2279 }
2280 buf2[buf2index] = 0;
2281 normalize_cipher_order(buf2);
2282 strncpy_s(pvar->settings.CipherOrder, sizeof(pvar->settings.CipherOrder), buf2, _TRUNCATE);
2283
2284 buf[0] = 0;
2285 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2286 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2287 sizeof(pvar->settings.KnownHostsFiles),
2288 buf);
2289 buf[0] = 0;
2290 bufindex = 0;
2291 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2292 for (i = 0; buf[i] != 0; i++) {
2293 if (buf[i] == ';') {
2294 buf[i] = 0;
2295 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2296 pvar->settings.KnownHostsFiles[j] = ';';
2297 j++;
2298 j += copy_teraterm_dir_relative_path(pvar->settings.
2299 KnownHostsFiles + j,
2300 sizeof(pvar->settings.
2301 KnownHostsFiles)
2302 - j, buf + bufindex);
2303 }
2304 bufindex = i + 1;
2305 }
2306 }
2307 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2308 pvar->settings.KnownHostsFiles[j] = ';';
2309 j++;
2310 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2311 sizeof(pvar->settings. KnownHostsFiles) - j,
2312 buf + bufindex);
2313 }
2314
2315 // get SSH HeartBeat(keep-alive)
2316 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2317 i = atoi(buf);
2318 if (i < 0)
2319 i = 60;
2320 pvar->settings.ssh_heartbeat_overtime = i;
2321
2322 }
2323
2324 static void move_cur_sel_delta(HWND listbox, int delta)
2325 {
2326 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2327 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2328 int newPos = curPos + delta;
2329 char buf[1024];
2330
2331 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2332 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2333
2334 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2335 buf[0] = 0;
2336 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2337 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2338 SendMessage(listbox, LB_INSERTSTRING, newPos,
2339 (LPARAM) (char FAR *) buf);
2340 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2341 }
2342 }
2343 }
2344
2345 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2346 int readonly)
2347 {
2348 OPENFILENAME params;
2349 char fullname_buf[2048] = "ssh_known_hosts";
2350
2351 params.lStructSize = sizeof(OPENFILENAME);
2352 params.hwndOwner = parent;
2353 params.lpstrFilter = NULL;
2354 params.lpstrCustomFilter = NULL;
2355 params.nFilterIndex = 0;
2356 buf[0] = 0;
2357 params.lpstrFile = fullname_buf;
2358 params.nMaxFile = sizeof(fullname_buf);
2359 params.lpstrFileTitle = NULL;
2360 params.lpstrInitialDir = NULL;
2361 if (readonly) {
2362 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar,
2363 "Choose a read-only known-hosts file to add");
2364 }
2365 else {
2366 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar,
2367 "Choose a read/write known-hosts file");
2368 }
2369 params.lpstrTitle = pvar->ts->UIMsg;
2370 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2371 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2372 params.lpstrDefExt = NULL;
2373
2374 if (GetOpenFileName(&params) != 0) {
2375 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2376 return 1;
2377 } else {
2378 int err = CommDlgExtendedError();
2379
2380 if (err != 0) {
2381 char buf[1024];
2382 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar,
2383 "Unable to display file dialog box: error %d");
2384 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, err);
2385 MessageBox(parent, buf, "TTSSH Error",
2386 MB_OK | MB_ICONEXCLAMATION);
2387 }
2388
2389 return 0;
2390 }
2391 }
2392
2393 static void choose_read_write_file(HWND dlg)
2394 {
2395 char buf[1024];
2396
2397 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2398 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2399 }
2400 }
2401
2402 static void choose_read_only_file(HWND dlg)
2403 {
2404 char buf[1024];
2405 char buf2[4096];
2406
2407 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2408 buf2[0] = 0;
2409 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2410 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2411 strncat_s(buf2, sizeof(buf2), ";", _TRUNCATE);
2412 }
2413 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2414 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2415 }
2416 }
2417
2418 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2419 LPARAM lParam)
2420 {
2421 LOGFONT logfont;
2422 HFONT font;
2423
2424 switch (msg) {
2425 case WM_INITDIALOG:
2426 SetWindowLong(dlg, DWL_USER, lParam);
2427 init_setup_dlg((PTInstVar) lParam, dlg);
2428
2429 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2430 GetObject(font, sizeof(LOGFONT), &logfont);
2431 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2432 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2433 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2434 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2435 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2436 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2437 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2438 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2439 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2440 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2441 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2442 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2443 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2444 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2445 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2446 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2447 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2448 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2449 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2450 }
2451 else {
2452 DlgSetupFont = NULL;
2453 }
2454
2455 return TRUE;
2456 case WM_COMMAND:
2457 switch (LOWORD(wParam)) {
2458 case IDOK:
2459 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER), dlg);
2460 EndDialog(dlg, 1);
2461 if (DlgSetupFont != NULL) {
2462 DeleteObject(DlgSetupFont);
2463 }
2464 return TRUE;
2465 case IDCANCEL: /* there isn't a cancel button, but other Windows
2466 UI things can send this message */
2467 EndDialog(dlg, 0);
2468 if (DlgSetupFont != NULL) {
2469 DeleteObject(DlgSetupFont);
2470 }
2471 return TRUE;
2472 case IDC_SSHMOVECIPHERUP:
2473 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2474 set_move_button_status(dlg);
2475 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2476 return TRUE;
2477 case IDC_SSHMOVECIPHERDOWN:
2478 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
2479 set_move_button_status(dlg);
2480 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2481 return TRUE;
2482 case IDC_SSHCIPHERPREFS:
2483 set_move_button_status(dlg);
2484 return TRUE;
2485 case IDC_CHOOSEREADWRITEFILE:
2486 choose_read_write_file(dlg);
2487 return TRUE;
2488 case IDC_CHOOSEREADONLYFILE:
2489 choose_read_only_file(dlg);
2490 return TRUE;
2491 }
2492 break;
2493 }
2494
2495 return FALSE;
2496 }
2497
2498
2499 //
2500 // SSH key generator dialog (2005.4.10 yutaka)
2501 //
2502
2503 typedef struct {
2504 RSA *rsa;
2505 DSA *dsa;
2506 } ssh_private_key_t;
2507
2508 static ssh_private_key_t private_key = {NULL, NULL};
2509
2510 typedef struct {
2511 RSA *rsa;
2512 DSA *dsa;
2513 } ssh_public_key_t;
2514
2515 static ssh_public_key_t public_key = {NULL, NULL};;
2516
2517 static void free_ssh_key(void)
2518 {
2519 // DSA_free(), RSA_free()��NULL���n�����������������B
2520 DSA_free(private_key.dsa);
2521 private_key.dsa = NULL;
2522 DSA_free(public_key.dsa);
2523 public_key.dsa = NULL;
2524
2525 RSA_free(private_key.rsa);
2526 private_key.rsa = NULL;
2527 RSA_free(public_key.rsa);
2528 public_key.rsa = NULL;
2529 }
2530
2531
2532 static BOOL generate_ssh_key(enum hostkey_type type)
2533 {
2534 int bits = 1024;
2535
2536 // if SSH key already is generated, should free the resource.
2537 free_ssh_key();
2538
2539 if (type == KEY_RSA1 || type == KEY_RSA) {
2540 RSA *priv = NULL;
2541 RSA *pub = NULL;
2542
2543 // private key
2544 priv = RSA_generate_key(bits, 35, NULL, NULL);
2545 if (priv == NULL)
2546 goto error;
2547 private_key.rsa = priv;
2548
2549 // public key
2550 pub = RSA_new();
2551 pub->n = BN_new();
2552 pub->e = BN_new();
2553 if (pub->n == NULL || pub->e == NULL) {
2554 RSA_free(pub);
2555 goto error;
2556 }
2557
2558 BN_copy(pub->n, priv->n);
2559 BN_copy(pub->e, priv->e);
2560 public_key.rsa = pub;
2561
2562 } else if (type == KEY_DSA) {
2563 DSA *priv = NULL;
2564 DSA *pub = NULL;
2565
2566 // private key
2567 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2568 if (priv == NULL)
2569 goto error;
2570 if (!DSA_generate_key(priv)) {
2571 // TODO: free 'priv'?
2572 goto error;
2573 }
2574 private_key.dsa = priv;
2575
2576 // public key
2577 pub = DSA_new();
2578 if (pub == NULL)
2579 goto error;
2580 pub->p = BN_new();
2581 pub->q = BN_new();
2582 pub->g = BN_new();
2583 pub->pub_key = BN_new();
2584 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2585 DSA_free(pub);
2586 goto error;
2587 }
2588
2589 BN_copy(pub->p, priv->p);
2590 BN_copy(pub->q, priv->q);
2591 BN_copy(pub->g, priv->g);
2592 BN_copy(pub->pub_key, priv->pub_key);
2593 public_key.dsa = pub;
2594
2595 } else {
2596 goto error;
2597 }
2598
2599 return TRUE;
2600
2601 error:
2602 free_ssh_key();
2603 return FALSE;
2604 }
2605
2606
2607 //
2608 // RC4
2609 //
2610
2611 /* Size of key to use */
2612 #define SEED_SIZE 20
2613
2614 /* Number of bytes to reseed after */
2615 #define REKEY_BYTES (1 << 24)
2616
2617 static int rc4_ready = 0;
2618 static RC4_KEY rc4;
2619
2620 static void seed_rng(void)
2621 {
2622 if (RAND_status() != 1)
2623 return;
2624 }
2625
2626 static void arc4random_stir(void)
2627 {
2628 unsigned char rand_buf[SEED_SIZE];
2629 int i;
2630
2631 memset(&rc4, 0, sizeof(rc4));
2632 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2633 //fatal("Couldn't obtain random bytes (error %ld)",
2634 // ERR_get_error());
2635 }
2636 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2637
2638 /*
2639 * Discard early keystream, as per recommendations in:
2640 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2641 */
2642 for(i = 0; i <= 256; i += sizeof(rand_buf))
2643 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2644
2645 memset(rand_buf, 0, sizeof(rand_buf));
2646
2647 rc4_ready = REKEY_BYTES;
2648 }
2649
2650 static unsigned int arc4random(void)
2651 {
2652 unsigned int r = 0;
2653 static int first_time = 1;
2654
2655 if (rc4_ready <= 0) {
2656 if (first_time) {
2657 seed_rng();
2658 }
2659 first_time = 0;
2660 arc4random_stir();
2661 }
2662
2663 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2664
2665 rc4_ready -= sizeof(r);
2666
2667 return(r);
2668 }
2669
2670 //
2671 // SSH1 3DES
2672 //
2673 /*
2674 * This is used by SSH1:
2675 *
2676 * What kind of triple DES are these 2 routines?
2677 *
2678 * Why is there a redundant initialization vector?
2679 *
2680 * If only iv3 was used, then, this would till effect have been
2681 * outer-cbc. However, there is also a private iv1 == iv2 which
2682 * perhaps makes differential analysis easier. On the other hand, the
2683 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2684 * result of that there is no longer any known iv1 to use when
2685 * choosing the X block.
2686 */
2687 struct ssh1_3des_ctx
2688 {
2689 EVP_CIPHER_CTX k1, k2, k3;
2690 };
2691
2692 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2693 {
2694 struct ssh1_3des_ctx *c;
2695 u_char *k1, *k2, *k3;
2696
2697 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2698 c = malloc(sizeof(*c));
2699 EVP_CIPHER_CTX_set_app_data(ctx, c);
2700 }
2701 if (key == NULL)
2702 return (1);
2703 if (enc == -1)
2704 enc = ctx->encrypt;
2705 k1 = k2 = k3 = (u_char *) key;
2706 k2 += 8;
2707 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2708 if (enc)
2709 k3 += 16;
2710 else
2711 k1 += 16;
2712 }
2713 EVP_CIPHER_CTX_init(&c->k1);
2714 EVP_CIPHER_CTX_init(&c->k2);
2715 EVP_CIPHER_CTX_init(&c->k3);
2716 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2717 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2718 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2719 memset(c, 0, sizeof(*c));
2720 free(c);
2721 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2722 return (0);
2723 }
2724 return (1);
2725 }
2726
2727 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2728 {
2729 struct ssh1_3des_ctx *c;
2730
2731 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2732 //error("ssh1_3des_cbc: no context");
2733 return (0);
2734 }
2735 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2736 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2737 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2738 return (0);
2739 return (1);
2740 }
2741
2742 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2743 {
2744 struct ssh1_3des_ctx *c;
2745
2746 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2747 EVP_CIPHER_CTX_cleanup(&c->k1);
2748 EVP_CIPHER_CTX_cleanup(&c->k2);
2749 EVP_CIPHER_CTX_cleanup(&c->k3);
2750 memset(c, 0, sizeof(*c));
2751 free(c);
2752 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2753 }
2754 return (1);
2755 }
2756
2757 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2758 {
2759 struct ssh1_3des_ctx *c;
2760
2761 if (len != 24)
2762 //fatal("%s: bad 3des iv length: %d", __func__, len);
2763 ;
2764
2765 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2766 //fatal("%s: no 3des context", __func__);
2767 ;
2768
2769 if (doset) {
2770 //debug3("%s: Installed 3DES IV", __func__);
2771 memcpy(c->k1.iv, iv, 8);
2772 memcpy(c->k2.iv, iv + 8, 8);
2773 memcpy(c->k3.iv, iv + 16, 8);
2774 } else {
2775 //debug3("%s: Copying 3DES IV", __func__);
2776 memcpy(iv, c->k1.iv, 8);
2777 memcpy(iv + 8, c->k2.iv, 8);
2778 memcpy(iv + 16, c->k3.iv, 8);
2779 }
2780 }
2781
2782 const EVP_CIPHER *evp_ssh1_3des(void)
2783 {
2784 static EVP_CIPHER ssh1_3des;
2785
2786 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2787 ssh1_3des.nid = NID_undef;
2788 ssh1_3des.block_size = 8;
2789 ssh1_3des.iv_len = 0;
2790 ssh1_3des.key_len = 16;
2791 ssh1_3des.init = ssh1_3des_init;
2792 ssh1_3des.cleanup = ssh1_3des_cleanup;
2793 ssh1_3des.do_cipher = ssh1_3des_cbc;
2794 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2795 return (&ssh1_3des);
2796 }
2797
2798 static void ssh_make_comment(char *comment, int maxlen)
2799 {
2800 char user[UNLEN + 1], host[128];
2801 DWORD dwSize;
2802 WSADATA wsaData;
2803 int ret;
2804
2805 // get Windows logon user name
2806 dwSize = sizeof(user);
2807 if (GetUserName(user, &dwSize) == 0) {
2808 strncpy_s(user, sizeof(user), "yutaka", _TRUNCATE);
2809 }
2810
2811 // get local hostname (by WinSock)
2812 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2813 if (ret == 0) {
2814 if (gethostname(host, sizeof(host)) != 0) {
2815 ret = WSAGetLastError();
2816 }
2817 WSACleanup();
2818 }
2819 if (ret != 0) {
2820 strncpy_s(host, sizeof(host), "sai", _TRUNCATE);
2821 }
2822
2823 _snprintf_s(comment, maxlen, _TRUNCATE, "%s@%s", user, host);
2824 }
2825
2826 // uuencode (rfc1521)
2827 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2828 {
2829 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2830 char pad = '=';
2831 int datalength = 0;
2832 unsigned char input[3];
2833 unsigned char output[4];
2834 int i;
2835
2836 while (srclen > 2) {
2837 input[0] = *src++;
2838 input[1] = *src++;
2839 input[2] = *src++;
2840 srclen -= 3;
2841
2842 output[0] = input[0] >> 2;
2843 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2844 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2845 output[3] = input[2] & 0x3f;
2846 if (output[0] >= 64 ||
2847 output[1] >= 64 ||
2848 output[2] >= 64 ||
2849 output[3] >= 64)
2850 return -1;
2851
2852 if (datalength + 4 > targsize)
2853 return (-1);
2854 target[datalength++] = base64[output[0]];
2855 target[datalength++] = base64[output[1]];
2856 target[datalength++] = base64[output[2]];
2857 target[datalength++] = base64[output[3]];
2858 }
2859
2860 if (srclen != 0) {
2861 /* Get what's left. */
2862 input[0] = input[1] = input[2] = '\0';
2863 for (i = 0; i < srclen; i++)
2864 input[i] = *src++;
2865
2866 output[0] = input[0] >> 2;
2867