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 3139 - (show annotations) (download) (as text)
Fri Aug 1 16:29:01 2008 UTC (15 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 117711 byte(s)
NT4.0で無理矢理32bitアイコンを表示しようとして崩れたアイコンが表示される問題を修正した。

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