Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/hosts.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8093 - (show annotations) (download) (as text)
Sun Sep 8 10:16:41 2019 UTC (4 years, 7 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 70618 byte(s)
・known_hostsダイアログおよびユーザ認証ダイアログの表示中に、SSHサーバ側からネットワーク切断された場合、ダイアログを自動で閉じるようにした。
・known_hostsダイアログの表示中にSSHサーバ側からネットワーク切断されると、アプリがクラッシュすることがある問題を修正した。
・SSH1: /nosecuritywarningオプションが機能していなかった問題を修正した。
・/nosecuritywarningオプションに関する注意事項を追記した。

branches/ttssh_improvedからリビジョン8036をマージ:
SSHサーバと認証中にネットワーク切断された場合、認証ダイアログが残ったままとならないようにした。

........
branches/ttssh_improvedからリビジョン8044をマージ:
r8036でダイアログの処理追加漏れ。
SSHサーバと認証中にネットワーク切断された場合、認証ダイアログが残ったままとならないようにした。

........

branches/ttssh_improvedからリビジョン8063をマージ:
known_hostsダイアログが表示されている状態で、サーバから切断を行うと、
TTXCloseTCPが呼び出され、TTSSHのリソースが解放されてしまう。
SSHハンドラの延長でknown_hostsダイアログを出して止まっているため、
ダイアログを閉じて、処理再開すると、SSHの内部情報が壊れる。
その状態で再度SSH接続しようとすると100%アプリが落ちる。

上記問題に対して、まずは SSH1 に処置した。

........

branches/ttssh_improvedからリビジョン8081をマージ:
known_hostsダイアログが表示されている状態で、サーバから切断を行うと、
TTXCloseTCPが呼び出され、TTSSHのリソースが解放されてしまう。
SSHハンドラの延長でknown_hostsダイアログを出して止まっているため、
ダイアログを閉じて、処理再開すると、SSHの内部情報が壊れる。
その状態で再度SSH接続しようとすると100%アプリが落ちる。

上記問題に対して、SSH2 に対応した。

パケット受信時のSSHハンドラのコンテキストで known_hosts ダイアログを表示
させていたが、TTXCloseTCPの非同期呼び出しに対処できないため、
TTSSH1で使われていたknown_hosts ダイアログの非同期呼び出しに
実装を変更した。
これにより、比較的大きくロジックの修正を行っている。

........

branches/ttssh_improvedからリビジョン8085をマージ:
前回のオプション指定(/nosecuritywarning)が残らないように初期化する。
........


1 /*
2 * Copyright (c) 1998-2001, Robert O'Callahan
3 * (C) 2004-2019 TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 This code is copyright (C) 1998-1999 Robert O'Callahan.
32 See LICENSE.TXT for the license.
33 */
34 #include "ttxssh.h"
35 #include "util.h"
36 #include "resource.h"
37 #include "matcher.h"
38 #include "ssh.h"
39 #include "key.h"
40 #include "hosts.h"
41 #include "dns.h"
42 #include "dlglib.h"
43 #include "compat_win.h"
44
45 #include <openssl/bn.h>
46 #include <openssl/evp.h>
47 #include <openssl/rsa.h>
48 #include <openssl/dsa.h>
49
50 #include <fcntl.h>
51 #include <io.h>
52 #include <errno.h>
53 #include <sys/stat.h>
54 #include <direct.h>
55 #include <memory.h>
56
57
58 #undef DialogBoxParam
59 #define DialogBoxParam(p1,p2,p3,p4,p5) \
60 TTDialogBoxParam(p1,p2,p3,p4,p5)
61 #undef EndDialog
62 #define EndDialog(p1,p2) \
63 TTEndDialog(p1, p2)
64
65 // BASE64�\���������i��������'='�����������������j
66 static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
67
68
69 BOOL HOSTS_resume_session_after_known_hosts(PTInstVar pvar);
70 void HOSTS_cancel_session_after_known_hosts(PTInstVar pvar);
71
72
73 static char **parse_multi_path(char *buf)
74 {
75 int i;
76 int ch;
77 int num_paths = 1;
78 char ** result;
79 int last_path_index;
80
81 for (i = 0; (ch = buf[i]) != 0; i++) {
82 if (ch == ';') {
83 num_paths++;
84 }
85 }
86
87 result =
88 (char **) malloc(sizeof(char *) * (num_paths + 1));
89
90 last_path_index = 0;
91 num_paths = 0;
92 for (i = 0; (ch = buf[i]) != 0; i++) {
93 if (ch == ';') {
94 buf[i] = 0;
95 result[num_paths] = _strdup(buf + last_path_index);
96 num_paths++;
97 buf[i] = ch;
98 last_path_index = i + 1;
99 }
100 }
101 if (i > last_path_index) {
102 result[num_paths] = _strdup(buf + last_path_index);
103 num_paths++;
104 }
105 result[num_paths] = NULL;
106 return result;
107 }
108
109 void HOSTS_init(PTInstVar pvar)
110 {
111 pvar->hosts_state.prefetched_hostname = NULL;
112 key_init(&pvar->hosts_state.hostkey);
113 pvar->hosts_state.hosts_dialog = NULL;
114 pvar->hosts_state.file_names = NULL;
115
116 /*
117 * �O�����I�v�V�����w��(/nosecuritywarning)���c���������������������������B
118 */
119 pvar->nocheck_known_hosts = FALSE;
120 }
121
122 void HOSTS_open(PTInstVar pvar)
123 {
124 pvar->hosts_state.file_names =
125 parse_multi_path(pvar->session_settings.KnownHostsFiles);
126 }
127
128 //
129 // known_hosts�t�@�C�������e�������� pvar->hosts_state.file_data ����������
130 //
131 static int begin_read_file(PTInstVar pvar, char *name,
132 int suppress_errors)
133 {
134 int fd;
135 int length;
136 int amount_read;
137 char buf[2048];
138
139 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
140 fd = _open(buf, _O_RDONLY | _O_SEQUENTIAL | _O_BINARY);
141 if (fd == -1) {
142 if (!suppress_errors) {
143 if (errno == ENOENT) {
144 UTIL_get_lang_msg("MSG_HOSTS_READ_ENOENT_ERROR", pvar,
145 "An error occurred while trying to read a known_hosts file.\n"
146 "The specified filename does not exist.");
147 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
148 } else {
149 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
150 "An error occurred while trying to read a known_hosts file.");
151 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
152 }
153 }
154 return 0;
155 }
156
157 length = (int) _lseek(fd, 0, SEEK_END);
158 _lseek(fd, 0, SEEK_SET);
159
160 if (length >= 0 && length < 0x7FFFFFFF) {
161 pvar->hosts_state.file_data = malloc(length + 1);
162 if (pvar->hosts_state.file_data == NULL) {
163 if (!suppress_errors) {
164 UTIL_get_lang_msg("MSG_HOSTS_ALLOC_ERROR", pvar,
165 "Memory ran out while trying to allocate space to read a known_hosts file.");
166 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
167 }
168 _close(fd);
169 return 0;
170 }
171 } else {
172 if (!suppress_errors) {
173 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
174 "An error occurred while trying to read a known_hosts file.");
175 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
176 }
177 _close(fd);
178 return 0;
179 }
180
181 amount_read = _read(fd, pvar->hosts_state.file_data, length);
182 pvar->hosts_state.file_data[length] = 0;
183
184 _close(fd);
185
186 if (amount_read != length) {
187 if (!suppress_errors) {
188 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
189 "An error occurred while trying to read a known_hosts file.");
190 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
191 }
192 free(pvar->hosts_state.file_data);
193 pvar->hosts_state.file_data = NULL;
194 return 0;
195 } else {
196 return 1;
197 }
198 }
199
200 static int end_read_file(PTInstVar pvar, int suppress_errors)
201 {
202 free(pvar->hosts_state.file_data);
203 pvar->hosts_state.file_data = NULL;
204 return 1;
205 }
206
207 static int begin_read_host_files(PTInstVar pvar, int suppress_errors)
208 {
209 pvar->hosts_state.file_num = 0;
210 pvar->hosts_state.file_data = NULL;
211 return 1;
212 }
213
214 // MIME64�����������X�L�b�v����
215 static int eat_base64(char *data)
216 {
217 int index = 0;
218 int ch;
219
220 for (;;) {
221 ch = data[index];
222 if (ch == '=' || strchr(base64, ch)) {
223 // BASE64���\�������������������� index ���i����
224 index++;
225 } else {
226 break;
227 }
228 }
229
230 return index;
231 }
232
233 static int eat_spaces(char *data)
234 {
235 int index = 0;
236 int ch;
237
238 while ((ch = data[index]) == ' ' || ch == '\t') {
239 index++;
240 }
241 return index;
242 }
243
244 static int eat_digits(char *data)
245 {
246 int index = 0;
247 int ch;
248
249 while ((ch = data[index]) >= '0' && ch <= '9') {
250 index++;
251 }
252 return index;
253 }
254
255 static int eat_to_end_of_line(char *data)
256 {
257 int index = 0;
258 int ch;
259
260 while ((ch = data[index]) != '\n' && ch != '\r' && ch != 0) {
261 index++;
262 }
263
264 while ((ch = data[index]) == '\n' || ch == '\r') {
265 index++;
266 }
267
268 return index;
269 }
270
271 static int eat_to_end_of_pattern(char *data)
272 {
273 int index = 0;
274 int ch;
275
276 while (ch = data[index], is_pattern_char(ch)) {
277 index++;
278 }
279
280 return index;
281 }
282
283 // SSH2���� BASE64 �`�����i�[����������
284 static Key *parse_base64data(char *data)
285 {
286 int count;
287 unsigned char *blob = NULL;
288 int len, n;
289 Key *key = NULL;
290 char ch;
291
292 // BASE64���������T�C�Y������
293 count = eat_base64(data);
294 len = 2 * count;
295 blob = malloc(len);
296 if (blob == NULL)
297 goto error;
298
299 // BASE64�f�R�[�h
300 ch = data[count];
301 data[count] = '\0'; // ���������s�R�[�h������������������������������������
302 n = b64decode(blob, len, data);
303 data[count] = ch;
304 if (n < 0) {
305 goto error;
306 }
307
308 key = key_from_blob(blob, n);
309 if (key == NULL)
310 goto error;
311
312 error:
313 if (blob != NULL)
314 free(blob);
315
316 return (key);
317 }
318
319
320 static char *parse_bignum(char *data)
321 {
322 uint32 digits = 0;
323 BIGNUM *num = BN_new();
324 BIGNUM *billion = BN_new();
325 BIGNUM *digits_num = BN_new();
326 BN_CTX *ctx = BN_CTX_new();
327 char *result;
328 int ch;
329 int leftover_digits = 1;
330
331 BN_CTX_init(ctx);
332 BN_set_word(num, 0);
333 BN_set_word(billion, 1000000000L);
334
335 while ((ch = *data) >= '0' && ch <= '9') {
336 if (leftover_digits == 1000000000L) {
337 BN_set_word(digits_num, digits);
338 BN_mul(num, num, billion, ctx);
339 BN_add(num, num, digits_num);
340 leftover_digits = 1;
341 digits = 0;
342 }
343
344 digits = digits * 10 + ch - '0';
345 leftover_digits *= 10;
346 data++;
347 }
348
349 BN_set_word(digits_num, digits);
350 BN_set_word(billion, leftover_digits);
351 BN_mul(num, num, billion, ctx);
352 BN_add(num, num, digits_num);
353
354 result = (char *) malloc(2 + BN_num_bytes(num));
355 set_ushort16_MSBfirst(result, BN_num_bits(num));
356 BN_bn2bin(num, result + 2);
357
358 BN_CTX_free(ctx);
359 BN_free(digits_num);
360 BN_free(num);
361 BN_free(billion);
362
363 return result;
364 }
365
366 //
367 // known_hosts�t�@�C�������e���������A�w�������z�X�g�����J�����T���B
368 //
369 static int check_host_key(PTInstVar pvar, char *hostname,
370 unsigned short tcpport, char *data,
371 Key *key)
372 {
373 int index = eat_spaces(data);
374 int matched = 0;
375 int keybits = 0;
376
377 if (data[index] == '#') {
378 return index + eat_to_end_of_line(data + index);
379 }
380
381 /* if we find an empty line, then it won't have any patterns matching the hostname
382 and so we skip it */
383 index--;
384 do {
385 int negated;
386 int bracketed;
387 char *end_bracket;
388 int host_matched = 0;
389 unsigned short keyfile_port = 22;
390
391 index++;
392 negated = data[index] == '!';
393
394 if (negated) {
395 index++;
396 bracketed = data[index] == '[';
397 if (bracketed) {
398 end_bracket = strstr(data + index + 1, "]:");
399 if (end_bracket != NULL) {
400 *end_bracket = ' ';
401 index++;
402 }
403 }
404 host_matched = match_pattern(data + index, hostname);
405 if (bracketed && end_bracket != NULL) {
406 *end_bracket = ']';
407 keyfile_port = atoi(end_bracket + 2);
408 }
409 if (host_matched && keyfile_port == tcpport) {
410 return index + eat_to_end_of_line(data + index);
411 }
412 } else {
413 bracketed = data[index] == '[';
414 if (bracketed) {
415 end_bracket = strstr(data + index + 1, "]:");
416 if (end_bracket != NULL) {
417 *end_bracket = ' ';
418 index++;
419 }
420 }
421 host_matched = match_pattern(data + index, hostname);
422 if (bracketed && end_bracket != NULL) {
423 *end_bracket = ']';
424 keyfile_port = atoi(end_bracket + 2);
425 }
426 if (host_matched && keyfile_port == tcpport) {
427 matched = 1;
428 }
429 }
430
431 index += eat_to_end_of_pattern(data + index);
432 } while (data[index] == ',');
433
434 if (!matched) {
435 return index + eat_to_end_of_line(data + index);
436 } else {
437 // ���������������t�H�[�}�b�g��������
438 // �����A���������v�����G���g�����������������������B
439 /*
440 [SSH1]
441 192.168.1.2 1024 35 13032....
442
443 [SSH2]
444 192.168.1.2 ssh-rsa AAAAB3NzaC1....
445 192.168.1.2 ssh-dss AAAAB3NzaC1....
446 192.168.1.2 rsa AAAAB3NzaC1....
447 192.168.1.2 dsa AAAAB3NzaC1....
448 192.168.1.2 rsa1 AAAAB3NzaC1....
449 */
450 int rsa1_key_bits;
451
452 index += eat_spaces(data + index);
453
454 rsa1_key_bits = atoi(data + index);
455 if (rsa1_key_bits > 0) { // RSA1������
456 if (!SSHv1(pvar)) { // SSH2��������������������
457 return index + eat_to_end_of_line(data + index);
458 }
459
460 key->type = KEY_RSA1;
461
462 key->bits = rsa1_key_bits;
463 index += eat_digits(data + index);
464 index += eat_spaces(data + index);
465
466 key->exp = parse_bignum(data + index);
467 index += eat_digits(data + index);
468 index += eat_spaces(data + index);
469
470 key->mod = parse_bignum(data + index);
471 } else {
472 char *cp, *p;
473 Key *key2;
474 ssh_keytype key_type;
475
476 if (!SSHv2(pvar)) { // SSH1��������������������
477 return index + eat_to_end_of_line(data + index);
478 }
479
480 cp = data + index;
481 p = strchr(cp, ' ');
482 if (p == NULL) {
483 return index + eat_to_end_of_line(data + index);
484 }
485 index += (p - cp); // setup index
486 *p = '\0';
487 key_type = get_keytype_from_name(cp);
488 *p = ' ';
489
490 index += eat_spaces(data + index); // update index
491
492 // base64 decode
493 key2 = parse_base64data(data + index);
494 if (key2 == NULL) {
495 return index + eat_to_end_of_line(data + index);
496 }
497
498 // setup
499 key->type = key2->type;
500 key->dsa = key2->dsa;
501 key->rsa = key2->rsa;
502 key->ecdsa = key2->ecdsa;
503 key->ed25519_pk = key2->ed25519_pk;
504
505 index += eat_base64(data + index);
506 index += eat_spaces(data + index);
507
508 // Key�\�������g���������� (2008.3.2 yutaka)
509 free(key2);
510 }
511
512 return index + eat_to_end_of_line(data + index);
513 }
514 }
515
516 //
517 // known_hosts�t�@�C�������z�X�g�������v�����s������
518 // return_always
519 // 0: �������������T��
520 // 1: 1�s�����T��������
521 //
522 static int read_host_key(PTInstVar pvar,
523 char *hostname, unsigned short tcpport,
524 int suppress_errors, int return_always,
525 Key *key)
526 {
527 int i;
528 int while_flg;
529
530 for (i = 0; hostname[i] != 0; i++) {
531 int ch = hostname[i];
532
533 if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
534 if (!suppress_errors) {
535 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
536 "The host name contains an invalid character.\n"
537 "This session will be terminated.");
538 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
539 }
540 return 0;
541 }
542 }
543
544 if (i == 0) {
545 if (!suppress_errors) {
546 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
547 "The host name should not be empty.\n"
548 "This session will be terminated.");
549 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
550 }
551 return 0;
552 }
553
554 // hostkey type is KEY_UNSPEC.
555 key_init(key);
556
557 do {
558 if (pvar->hosts_state.file_data == NULL
559 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
560 char *filename;
561 int keep_going = 1;
562
563 if (pvar->hosts_state.file_data != NULL) {
564 end_read_file(pvar, suppress_errors);
565 }
566
567 do {
568 filename =
569 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
570
571 if (filename == NULL) {
572 return 1;
573 } else {
574 pvar->hosts_state.file_num++;
575
576 if (filename[0] != 0) {
577 if (begin_read_file(pvar, filename, suppress_errors)) {
578 pvar->hosts_state.file_data_index = 0;
579 keep_going = 0;
580 }
581 }
582 }
583 } while (keep_going);
584 }
585
586 pvar->hosts_state.file_data_index +=
587 check_host_key(pvar, hostname, tcpport,
588 pvar->hosts_state.file_data +
589 pvar->hosts_state.file_data_index,
590 key);
591
592 if (!return_always) {
593 // �L�����L�[��������������
594 while_flg = (key->type == KEY_UNSPEC);
595 }
596 else {
597 while_flg = 0;
598 }
599 } while (while_flg);
600
601 return 1;
602 }
603
604 static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
605 {
606 if (pvar->hosts_state.file_data != NULL) {
607 end_read_file(pvar, suppress_errors);
608 }
609 }
610
611 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
612 void HOSTS_prefetch_host_key(PTInstVar pvar, char *hostname, unsigned short tcpport)
613 {
614 Key key; // known_hosts���o�^������������
615
616 if (!begin_read_host_files(pvar, 1)) {
617 return;
618 }
619
620 memset(&key, 0, sizeof(key));
621 if (!read_host_key(pvar, hostname, tcpport, 1, 0, &key)) {
622 return;
623 }
624
625 key_copy(&pvar->hosts_state.hostkey, &key);
626 key_init(&key);
627
628 free(pvar->hosts_state.prefetched_hostname);
629 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
630
631 finish_read_host_files(pvar, 1);
632 }
633
634
635 // known_hosts�t�@�C�������Y�������L�[���������������B
636 //
637 // return:
638 // *keyptr != NULL ��������
639 //
640 static int parse_hostkey_file(PTInstVar pvar, char *hostname,
641 unsigned short tcpport, char *data, Key **keyptr)
642 {
643 int index = eat_spaces(data);
644 int matched = 0;
645 int keybits = 0;
646 ssh_keytype ktype;
647 Key *key;
648
649 *keyptr = NULL;
650
651 if (data[index] == '#') {
652 return index + eat_to_end_of_line(data + index);
653 }
654
655 /* if we find an empty line, then it won't have any patterns matching the hostname
656 and so we skip it */
657 index--;
658 do {
659 int negated;
660 int bracketed;
661 char *end_bracket;
662 int host_matched = 0;
663 unsigned short keyfile_port = 22;
664
665 index++;
666 negated = data[index] == '!';
667
668 if (negated) {
669 index++;
670 bracketed = data[index] == '[';
671 if (bracketed) {
672 end_bracket = strstr(data + index + 1, "]:");
673 if (end_bracket != NULL) {
674 *end_bracket = ' ';
675 index++;
676 }
677 }
678 host_matched = match_pattern(data + index, hostname);
679 if (bracketed && end_bracket != NULL) {
680 *end_bracket = ']';
681 keyfile_port = atoi(end_bracket + 2);
682 }
683 if (host_matched && keyfile_port == tcpport) {
684 return index + eat_to_end_of_line(data + index);
685 }
686 }
687 else {
688 bracketed = data[index] == '[';
689 if (bracketed) {
690 end_bracket = strstr(data + index + 1, "]:");
691 if (end_bracket != NULL) {
692 *end_bracket = ' ';
693 index++;
694 }
695 }
696 host_matched = match_pattern(data + index, hostname);
697 if (bracketed && end_bracket != NULL) {
698 *end_bracket = ']';
699 keyfile_port = atoi(end_bracket + 2);
700 }
701 if (host_matched && keyfile_port == tcpport) {
702 matched = 1;
703 }
704 }
705
706 index += eat_to_end_of_pattern(data + index);
707 } while (data[index] == ',');
708
709 if (!matched) {
710 return index + eat_to_end_of_line(data + index);
711 }
712 else {
713 // ���������������t�H�[�}�b�g��������
714 // �����A���������v�����G���g�����������������������B
715 /*
716 [SSH1]
717 192.168.1.2 1024 35 13032....
718
719 [SSH2]
720 192.168.1.2 ssh-rsa AAAAB3NzaC1....
721 192.168.1.2 ssh-dss AAAAB3NzaC1....
722 192.168.1.2 rsa AAAAB3NzaC1....
723 192.168.1.2 dsa AAAAB3NzaC1....
724 192.168.1.2 rsa1 AAAAB3NzaC1....
725 */
726 int rsa1_key_bits;
727
728 index += eat_spaces(data + index);
729
730 rsa1_key_bits = atoi(data + index);
731 if (rsa1_key_bits > 0) { // RSA1������
732 if (!SSHv1(pvar)) { // SSH2��������������������
733 return index + eat_to_end_of_line(data + index);
734 }
735
736 key = key_new(KEY_RSA1);
737 key->bits = rsa1_key_bits;
738
739 index += eat_digits(data + index);
740 index += eat_spaces(data + index);
741 key->exp = parse_bignum(data + index);
742
743 index += eat_digits(data + index);
744 index += eat_spaces(data + index);
745 key->mod = parse_bignum(data + index);
746
747 // setup
748 *keyptr = key;
749
750 }
751 else {
752 char *cp, *p;
753
754 if (!SSHv2(pvar)) { // SSH1��������������������
755 return index + eat_to_end_of_line(data + index);
756 }
757
758 cp = data + index;
759 p = strchr(cp, ' ');
760 if (p == NULL) {
761 return index + eat_to_end_of_line(data + index);
762 }
763 index += (p - cp); // setup index
764 *p = '\0';
765 ktype = get_keytype_from_name(cp);
766 *p = ' ';
767
768 index += eat_spaces(data + index); // update index
769
770 // base64 decode
771 key = parse_base64data(data + index);
772 if (key == NULL) {
773 return index + eat_to_end_of_line(data + index);
774 }
775
776 // setup
777 *keyptr = key;
778
779 index += eat_base64(data + index);
780 index += eat_spaces(data + index);
781 }
782
783 return index + eat_to_end_of_line(data + index);
784 }
785 }
786
787 // known_hosts�t�@�C�������z�X�g���J�������������B
788 // �������������������������������AHost key rotation�p���V�K���p�������B
789 //
790 // return 1: success
791 // 0: fail
792 int HOSTS_hostkey_foreach(PTInstVar pvar, hostkeys_foreach_fn *callback, void *ctx)
793 {
794 int success = 0;
795 int suppress_errors = 1;
796 unsigned short tcpport;
797 char *filename;
798 char *hostname;
799 Key *key;
800
801 if (!begin_read_host_files(pvar, 1)) {
802 goto error;
803 }
804
805 // Host key rotation�����Aknown_hosts �t�@�C�������������������A
806 // ������������1�������t�@�C�������������i2�������t�@�C����ReadOnly�������j�B
807 filename = pvar->hosts_state.file_names[pvar->hosts_state.file_num];
808 pvar->hosts_state.file_num++;
809
810 pvar->hosts_state.file_data_index = -1;
811 if (filename[0] != 0) {
812 if (begin_read_file(pvar, filename, suppress_errors)) {
813 pvar->hosts_state.file_data_index = 0;
814 }
815 }
816 if (pvar->hosts_state.file_data_index == -1)
817 goto error;
818
819 // ���������������z�X�g�����|�[�g�����B
820 hostname = pvar->ssh_state.hostname;
821 tcpport = pvar->ssh_state.tcpport;
822
823 // known_hosts�t�@�C�������e�������� pvar->hosts_state.file_data �������������������B
824 // ������ \0 �B
825 while (pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] != 0) {
826 key = NULL;
827
828 pvar->hosts_state.file_data_index +=
829 parse_hostkey_file(pvar, hostname, tcpport,
830 pvar->hosts_state.file_data +
831 pvar->hosts_state.file_data_index,
832 &key);
833
834 // �Y�����������������������A�R�[���o�b�N�����������o���B
835 if (key != NULL) {
836 if (callback(key, ctx) == 0)
837 key_free(key);
838 }
839 }
840
841 success = 1;
842
843 error:
844 finish_read_host_files(pvar, 1);
845
846 return (success);
847 }
848
849
850 static BOOL equal_mp_ints(unsigned char *num1,
851 unsigned char *num2)
852 {
853 if (num1 == NULL || num2 == NULL) {
854 return FALSE;
855 } else {
856 uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
857
858 if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
859 return FALSE; /* different byte lengths */
860 } else {
861 return memcmp(num1 + 2, num2 + 2, bytes) == 0;
862 }
863 }
864 }
865
866
867 // ���J�������r���s���B
868 //
869 // return
870 // -1 ... �����^������
871 // 0 ... ����������
872 // 1 ... ������
873 int HOSTS_compare_public_key(Key *src, Key *key)
874 {
875 int bits;
876 unsigned char *exp;
877 unsigned char *mod;
878 const EC_GROUP *group;
879 const EC_POINT *pa, *pb;
880 Key *a, *b;
881
882 if (src->type != key->type) {
883 return -1;
884 }
885
886 switch (key->type) {
887 case KEY_RSA1: // SSH1 host public key
888 bits = key->bits;
889 exp = key->exp;
890 mod = key->mod;
891
892 /* just check for equal exponent and modulus */
893 return equal_mp_ints(exp, src->exp)
894 && equal_mp_ints(mod, src->mod);
895 /*
896 return equal_mp_ints(exp, pvar->hosts_state.key_exp)
897 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
898 */
899
900 case KEY_RSA: // SSH2 RSA host public key
901 return key->rsa != NULL && src->rsa != NULL &&
902 BN_cmp(key->rsa->e, src->rsa->e) == 0 &&
903 BN_cmp(key->rsa->n, src->rsa->n) == 0;
904
905 case KEY_DSA: // SSH2 DSA host public key
906 return key->dsa != NULL && src->dsa &&
907 BN_cmp(key->dsa->p, src->dsa->p) == 0 &&
908 BN_cmp(key->dsa->q, src->dsa->q) == 0 &&
909 BN_cmp(key->dsa->g, src->dsa->g) == 0 &&
910 BN_cmp(key->dsa->pub_key, src->dsa->pub_key) == 0;
911
912 case KEY_ECDSA256:
913 case KEY_ECDSA384:
914 case KEY_ECDSA521:
915 if (key->ecdsa == NULL || src->ecdsa == NULL) {
916 return FALSE;
917 }
918 group = EC_KEY_get0_group(key->ecdsa);
919 pa = EC_KEY_get0_public_key(key->ecdsa),
920 pb = EC_KEY_get0_public_key(src->ecdsa);
921 return EC_POINT_cmp(group, pa, pb, NULL) == 0;
922
923 case KEY_ED25519:
924 a = key;
925 b = src;
926 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
927 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
928
929 default:
930 return FALSE;
931 }
932 }
933
934 #if 0
935 // pvar->hosts_state.hostkey ���n���������J����������������������
936 // -1 ... �����^������
937 // 0 ... ����������
938 // 1 ... ������
939 static int match_key(PTInstVar pvar, Key *key)
940 {
941 return HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key);
942 }
943 #endif
944
945 static void hosts_dlg_set_fingerprint(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg)
946 {
947 char *fp = NULL;
948
949 // fingerprint����������
950 switch (dgst_alg) {
951 case SSH_DIGEST_MD5:
952 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX, dgst_alg);
953 if (fp != NULL) {
954 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
955 free(fp);
956 }
957 break;
958 case SSH_DIGEST_SHA256:
959 default:
960 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_BASE64, SSH_DIGEST_SHA256);
961 if (fp != NULL) {
962 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
963 free(fp);
964 }
965 break;
966 }
967
968 // �r�W���A����fingerprint���\������
969 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART, dgst_alg);
970 if (fp != NULL) {
971 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
972 free(fp);
973 }
974 }
975
976 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
977 {
978 char buf[1024];
979 char buf2[2048];
980 int i, j;
981 int ch;
982
983 // static text�� # �������z�X�g�����u������
984 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
985 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
986 buf2[i] = ch;
987 }
988 strncpy_s(buf2 + i, sizeof(buf2) - i,
989 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
990 j = i + strlen(buf2 + i);
991 for (; buf[i] == '#'; i++) {
992 }
993 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
994
995 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
996
997 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
998 if (pvar->hFontFixed != NULL) {
999 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
1000 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
1001 }
1002
1003 CheckDlgButton(dlg, IDC_FP_HASH_ALG_SHA256, TRUE);
1004 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
1005 }
1006
1007 static int print_mp_int(char *buf, unsigned char *mp)
1008 {
1009 int i = 0, j, k;
1010 BIGNUM *num = BN_new();
1011 int ch;
1012
1013 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
1014
1015 do {
1016 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
1017 i++;
1018 } while (!BN_is_zero(num));
1019
1020 /* we need to reverse the digits */
1021 for (j = 0, k = i - 1; j < k; j++, k--) {
1022 ch = buf[j];
1023 buf[j] = buf[k];
1024 buf[k] = ch;
1025 }
1026
1027 buf[i] = 0;
1028 return i;
1029 }
1030
1031 //
1032 // known_hosts �t�@�C�������������G���g�������������B
1033 //
1034 static char *format_host_key(PTInstVar pvar)
1035 {
1036 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
1037 char *result = NULL;
1038 int index;
1039 ssh_keytype type = pvar->hosts_state.hostkey.type;
1040
1041 switch (type) {
1042 case KEY_RSA1:
1043 {
1044 int result_len = host_len + 50 + 8 +
1045 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
1046 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
1047 result = (char *) malloc(result_len);
1048
1049 if (pvar->ssh_state.tcpport == 22) {
1050 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
1051 index = host_len;
1052 }
1053 else {
1054 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1055 pvar->hosts_state.prefetched_hostname,
1056 pvar->ssh_state.tcpport);
1057 index = strlen(result);
1058 }
1059
1060 // ��2����(sizeOfBuffer)���w�������������A�������o�b�t�@�T�C�Y����
1061 // �����������������������C�������B
1062 // �|�[�g������22���O�������AVS2005��debug build�����Aadd_host_key()��
1063 // free(keydata)���A���������u�u���[�N�|�C���g���������������B�q�[�v������������������
1064 // �����������l�����������B�v���������O�����������B
1065 // release build�����������������B
1066 _snprintf_s(result + index, result_len - index, _TRUNCATE,
1067 " %d ", pvar->hosts_state.hostkey.bits);
1068 index += strlen(result + index);
1069 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
1070 result[index] = ' ';
1071 index++;
1072 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
1073 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1074
1075 break;
1076 }
1077
1078 case KEY_RSA:
1079 case KEY_DSA:
1080 case KEY_ECDSA256:
1081 case KEY_ECDSA384:
1082 case KEY_ECDSA521:
1083 case KEY_ED25519:
1084 {
1085 Key *key = &pvar->hosts_state.hostkey;
1086 char *blob = NULL;
1087 int blen, uulen, msize;
1088 char *uu = NULL;
1089 int n;
1090
1091 key_to_blob(key, &blob, &blen);
1092 uulen = 2 * blen;
1093 uu = malloc(uulen);
1094 if (uu == NULL) {
1095 goto error;
1096 }
1097 n = uuencode(blob, blen, uu, uulen);
1098 if (n > 0) {
1099 msize = host_len + 50 + uulen;
1100 result = malloc(msize);
1101 if (result == NULL) {
1102 goto error;
1103 }
1104
1105 // setup
1106 if (pvar->ssh_state.tcpport == 22) {
1107 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1108 pvar->hosts_state.prefetched_hostname,
1109 get_sshname_from_key(key),
1110 uu);
1111 } else {
1112 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1113 pvar->hosts_state.prefetched_hostname,
1114 pvar->ssh_state.tcpport,
1115 get_sshname_from_key(key),
1116 uu);
1117 }
1118 }
1119 error:
1120 if (blob != NULL)
1121 free(blob);
1122 if (uu != NULL)
1123 free(uu);
1124
1125 break;
1126 }
1127
1128 default:
1129 return NULL;
1130
1131 }
1132
1133 return result;
1134 }
1135
1136 static char *format_specified_host_key(Key *key, char *hostname, unsigned short tcpport)
1137 {
1138 int host_len = strlen(hostname);
1139 char *result = NULL;
1140 int index;
1141 ssh_keytype type = key->type;
1142
1143 switch (type) {
1144 case KEY_RSA1:
1145 {
1146 int result_len = host_len + 50 + 8 +
1147 get_ushort16_MSBfirst(key->exp) / 3 +
1148 get_ushort16_MSBfirst(key->mod) / 3;
1149 result = (char *) malloc(result_len);
1150
1151 if (tcpport == 22) {
1152 strncpy_s(result, result_len, hostname, _TRUNCATE);
1153 index = host_len;
1154 }
1155 else {
1156 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1157 hostname,
1158 tcpport);
1159 index = strlen(result);
1160 }
1161
1162 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
1163 " %d ", key->bits);
1164 index += strlen(result + index);
1165 index += print_mp_int(result + index, key->exp);
1166 result[index] = ' ';
1167 index++;
1168 index += print_mp_int(result + index, key->mod);
1169 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1170
1171 break;
1172 }
1173
1174 case KEY_RSA:
1175 case KEY_DSA:
1176 case KEY_ECDSA256:
1177 case KEY_ECDSA384:
1178 case KEY_ECDSA521:
1179 case KEY_ED25519:
1180 {
1181 //Key *key = &pvar->hosts_state.hostkey;
1182 char *blob = NULL;
1183 int blen, uulen, msize;
1184 char *uu = NULL;
1185 int n;
1186
1187 key_to_blob(key, &blob, &blen);
1188 uulen = 2 * blen;
1189 uu = malloc(uulen);
1190 if (uu == NULL) {
1191 goto error;
1192 }
1193 n = uuencode(blob, blen, uu, uulen);
1194 if (n > 0) {
1195 msize = host_len + 50 + uulen;
1196 result = malloc(msize);
1197 if (result == NULL) {
1198 goto error;
1199 }
1200
1201 // setup
1202 if (tcpport == 22) {
1203 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1204 hostname,
1205 get_sshname_from_key(key),
1206 uu);
1207 }
1208 else {
1209 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1210 hostname,
1211 tcpport,
1212 get_sshname_from_key(key),
1213 uu);
1214 }
1215 }
1216 error:
1217 if (blob != NULL)
1218 free(blob);
1219 if (uu != NULL)
1220 free(uu);
1221
1222 break;
1223 }
1224
1225 default:
1226 return NULL;
1227
1228 }
1229
1230 return result;
1231 }
1232
1233 static void add_host_key(PTInstVar pvar)
1234 {
1235 char *name = NULL;
1236
1237 if ( pvar->hosts_state.file_names != NULL)
1238 name = pvar->hosts_state.file_names[0];
1239
1240 if (name == NULL || name[0] == 0) {
1241 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1242 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1243 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1244 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1245 } else {
1246 char *keydata = format_host_key(pvar);
1247 int length = strlen(keydata);
1248 int fd;
1249 int amount_written;
1250 int close_result;
1251 char buf[FILENAME_MAX];
1252
1253 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1254 fd = _open(buf,
1255 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1256 _S_IREAD | _S_IWRITE);
1257 if (fd == -1) {
1258 if (errno == EACCES) {
1259 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1260 "An error occurred while trying to write the host key.\n"
1261 "You do not have permission to write to the known-hosts file.");
1262 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1263 } else {
1264 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1265 "An error occurred while trying to write the host key.\n"
1266 "The host key could not be written.");
1267 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1268 }
1269 return;
1270 }
1271
1272 amount_written = _write(fd, keydata, length);
1273 free(keydata);
1274 close_result = _close(fd);
1275
1276 if (amount_written != length || close_result == -1) {
1277 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1278 "An error occurred while trying to write the host key.\n"
1279 "The host key could not be written.");
1280 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1281 }
1282 }
1283 }
1284
1285 // �w�������L�[�� known_hosts �����������B
1286 void HOSTS_add_host_key(PTInstVar pvar, Key *key)
1287 {
1288 char *name = NULL;
1289 char *hostname;
1290 unsigned short tcpport;
1291
1292 hostname = pvar->ssh_state.hostname;
1293 tcpport = pvar->ssh_state.tcpport;
1294
1295 if (pvar->hosts_state.file_names != NULL)
1296 name = pvar->hosts_state.file_names[0];
1297
1298 if (name == NULL || name[0] == 0) {
1299 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1300 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1301 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1302 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1303 }
1304 else {
1305 char *keydata = format_specified_host_key(key, hostname, tcpport);
1306 int length = strlen(keydata);
1307 int fd;
1308 int amount_written;
1309 int close_result;
1310 char buf[FILENAME_MAX];
1311
1312 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1313 fd = _open(buf,
1314 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1315 _S_IREAD | _S_IWRITE);
1316 if (fd == -1) {
1317 if (errno == EACCES) {
1318 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1319 "An error occurred while trying to write the host key.\n"
1320 "You do not have permission to write to the known-hosts file.");
1321 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1322 }
1323 else {
1324 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1325 "An error occurred while trying to write the host key.\n"
1326 "The host key could not be written.");
1327 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1328 }
1329 return;
1330 }
1331
1332 amount_written = _write(fd, keydata, length);
1333 free(keydata);
1334 close_result = _close(fd);
1335
1336 if (amount_written != length || close_result == -1) {
1337 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1338 "An error occurred while trying to write the host key.\n"
1339 "The host key could not be written.");
1340 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1341 }
1342 }
1343 }
1344
1345 //
1346 // �����z�X�g�����e���������L�[����������
1347 // add_host_key ����������������
1348 //
1349 static void delete_different_key(PTInstVar pvar)
1350 {
1351 char *name = pvar->hosts_state.file_names[0];
1352
1353 if (name == NULL || name[0] == 0) {
1354 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1355 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1356 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1357 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1358 }
1359 else {
1360 Key key; // known_hosts���o�^������������
1361 int length;
1362 char filename[MAX_PATH];
1363 char tmp[L_tmpnam];
1364 int fd;
1365 int amount_written = 0;
1366 int close_result;
1367 int data_index = 0;
1368 char buf[FILENAME_MAX];
1369
1370 // �������������t�@�C�����J��
1371 _getcwd(filename, sizeof(filename));
1372 tmpnam_s(tmp,sizeof(tmp));
1373 strcat_s(filename, sizeof(filename), tmp);
1374 fd = _open(filename,
1375 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1376 _S_IREAD | _S_IWRITE);
1377
1378 if (fd == -1) {
1379 if (errno == EACCES) {
1380 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1381 "An error occurred while trying to write the host key.\n"
1382 "You do not have permission to write to the known-hosts file.");
1383 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1384 } else {
1385 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1386 "An error occurred while trying to write the host key.\n"
1387 "The host key could not be written.");
1388 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1389 }
1390 return;
1391 }
1392
1393 // �t�@�C��������������
1394 memset(&key, 0, sizeof(key));
1395 begin_read_host_files(pvar, 0);
1396 do {
1397 int host_index = 0;
1398 int matched = 0;
1399 int keybits = 0;
1400 char *data;
1401 int do_write = 0;
1402 length = amount_written = 0;
1403
1404 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1405 break;
1406 }
1407
1408 if (data_index == pvar->hosts_state.file_data_index) {
1409 // index ���i������ == ��������������
1410 break;
1411 }
1412
1413 data = pvar->hosts_state.file_data + data_index;
1414 host_index = eat_spaces(data);
1415
1416 if (data[host_index] == '#') {
1417 do_write = 1;
1418 }
1419 else {
1420 // �z�X�g������
1421 host_index--;
1422 do {
1423 int negated;
1424 int bracketed;
1425 char *end_bracket;
1426 int host_matched = 0;
1427 unsigned short keyfile_port = 22;
1428
1429 host_index++;
1430 negated = data[host_index] == '!';
1431
1432 if (negated) {
1433 host_index++;
1434 bracketed = data[host_index] == '[';
1435 if (bracketed) {
1436 end_bracket = strstr(data + host_index + 1, "]:");
1437 if (end_bracket != NULL) {
1438 *end_bracket = ' ';
1439 host_index++;
1440 }
1441 }
1442 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1443 if (bracketed && end_bracket != NULL) {
1444 *end_bracket = ']';
1445 keyfile_port = atoi(end_bracket + 2);
1446 }
1447 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1448 matched = 0;
1449 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1450 host_index--;
1451 do {
1452 host_index++;
1453 host_index += eat_to_end_of_pattern(data + host_index);
1454 } while (data[host_index] == ',');
1455 break;
1456 }
1457 }
1458 else {
1459 bracketed = data[host_index] == '[';
1460 if (bracketed) {
1461 end_bracket = strstr(data + host_index + 1, "]:");
1462 if (end_bracket != NULL) {
1463 *end_bracket = ' ';
1464 host_index++;
1465 }
1466 }
1467 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1468 if (bracketed && end_bracket != NULL) {
1469 *end_bracket = ']';
1470 keyfile_port = atoi(end_bracket + 2);
1471 }
1472 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1473 matched = 1;
1474 }
1475 }
1476 host_index += eat_to_end_of_pattern(data + host_index);
1477 } while (data[host_index] == ',');
1478
1479 // �z�X�g������������
1480 if (!matched) {
1481 do_write = 1;
1482 }
1483 // �z�X�g��������
1484 else {
1485 // �����`�������� or ���v�����L�[
1486 if (HOSTS_compare_public_key(&pvar->hosts_state.hostkey, &key) != 0) {
1487 do_write = 1;
1488 }
1489 // �����`�������������v�������L�[���X�L�b�v������
1490 }
1491 }
1492
1493 // ������������
1494 if (do_write) {
1495 length = pvar->hosts_state.file_data_index - data_index;
1496 amount_written =
1497 _write(fd, pvar->hosts_state.file_data + data_index,
1498 length);
1499
1500 if (amount_written != length) {
1501 goto error1;
1502 }
1503 }
1504 data_index = pvar->hosts_state.file_data_index;
1505 } while (1); // ������������
1506
1507 error1:
1508 close_result = _close(fd);
1509 if (amount_written != length || close_result == -1) {
1510 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1511 "An error occurred while trying to write the host key.\n"
1512 "The host key could not be written.");
1513 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1514 goto error2;
1515 }
1516
1517 // �������������t�@�C���������l�[��
1518 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1519 _unlink(buf);
1520 rename(filename, buf);
1521
1522 error2:
1523 _unlink(filename);
1524
1525 finish_read_host_files(pvar, 0);
1526
1527 // ���������������������������B
1528 key_init(&key);
1529 }
1530 }
1531
1532
1533 void HOSTS_delete_all_hostkeys(PTInstVar pvar)
1534 {
1535 char *name = pvar->hosts_state.file_names[0];
1536 char *hostname;
1537 unsigned short tcpport;
1538
1539 hostname = pvar->ssh_state.hostname;
1540 tcpport = pvar->ssh_state.tcpport;
1541
1542 if (name == NULL || name[0] == 0) {
1543 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1544 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1545 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1546 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1547 }
1548 else {
1549 Key key; // known_hosts���o�^������������
1550 int length;
1551 char filename[MAX_PATH];
1552 char tmp[L_tmpnam];
1553 int fd;
1554 int amount_written = 0;
1555 int close_result;
1556 int data_index = 0;
1557 char buf[FILENAME_MAX];
1558
1559 // �������������t�@�C�����J��
1560 _getcwd(filename, sizeof(filename));
1561 tmpnam_s(tmp, sizeof(tmp));
1562 strcat_s(filename, sizeof(filename), tmp);
1563 fd = _open(filename,
1564 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1565 _S_IREAD | _S_IWRITE);
1566
1567 if (fd == -1) {
1568 if (errno == EACCES) {
1569 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1570 "An error occurred while trying to write the host key.\n"
1571 "You do not have permission to write to the known-hosts file.");
1572 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1573 }
1574 else {
1575 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1576 "An error occurred while trying to write the host key.\n"
1577 "The host key could not be written.");
1578 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1579 }
1580 return;
1581 }
1582
1583 // �t�@�C��������������
1584 memset(&key, 0, sizeof(key));
1585 begin_read_host_files(pvar, 0);
1586 do {
1587 int host_index = 0;
1588 int matched = 0;
1589 int keybits = 0;
1590 char *data;
1591 int do_write = 0;
1592 length = amount_written = 0;
1593
1594 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1595 break;
1596 }
1597
1598 if (data_index == pvar->hosts_state.file_data_index) {
1599 // index ���i������ == ��������������
1600 break;
1601 }
1602
1603 data = pvar->hosts_state.file_data + data_index;
1604 host_index = eat_spaces(data);
1605
1606 if (data[host_index] == '#') {
1607 do_write = 1;
1608 }
1609 else {
1610 // �z�X�g������
1611 host_index--;
1612 do {
1613 int negated;
1614 int bracketed;
1615 char *end_bracket;
1616 int host_matched = 0;
1617 unsigned short keyfile_port = 22;
1618
1619 host_index++;
1620 negated = data[host_index] == '!';
1621
1622 if (negated) {
1623 host_index++;
1624 bracketed = data[host_index] == '[';
1625 if (bracketed) {
1626 end_bracket = strstr(data + host_index + 1, "]:");
1627 if (end_bracket != NULL) {
1628 *end_bracket = ' ';
1629 host_index++;
1630 }
1631 }
1632 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1633 if (bracketed && end_bracket != NULL) {
1634 *end_bracket = ']';
1635 keyfile_port = atoi(end_bracket + 2);
1636 }
1637 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1638 matched = 0;
1639 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1640 host_index--;
1641 do {
1642 host_index++;
1643 host_index += eat_to_end_of_pattern(data + host_index);
1644 } while (data[host_index] == ',');
1645 break;
1646 }
1647 }
1648 else {
1649 bracketed = data[host_index] == '[';
1650 if (bracketed) {
1651 end_bracket = strstr(data + host_index + 1, "]:");
1652 if (end_bracket != NULL) {
1653 *end_bracket = ' ';
1654 host_index++;
1655 }
1656 }
1657 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1658 if (bracketed && end_bracket != NULL) {
1659 *end_bracket = ']';
1660 keyfile_port = atoi(end_bracket + 2);
1661 }
1662 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1663 matched = 1;
1664 }
1665 }
1666 host_index += eat_to_end_of_pattern(data + host_index);
1667 } while (data[host_index] == ',');
1668
1669 // �z�X�g������������
1670 if (!matched) {
1671 do_write = 1;
1672 }
1673 // �z�X�g��������
1674 else {
1675 // ���������������������B
1676
1677 }
1678 }
1679
1680 // ������������
1681 if (do_write) {
1682 length = pvar->hosts_state.file_data_index - data_index;
1683 amount_written =
1684 _write(fd, pvar->hosts_state.file_data + data_index,
1685 length);
1686
1687 if (amount_written != length) {
1688 goto error1;
1689 }
1690 }
1691 data_index = pvar->hosts_state.file_data_index;
1692 } while (1); // ������������
1693
1694 error1:
1695 close_result = _close(fd);
1696 if (amount_written != length || close_result == -1) {
1697 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1698 "An error occurred while trying to write the host key.\n"
1699 "The host key could not be written.");
1700 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1701 goto error2;
1702 }
1703
1704 // �������������t�@�C���������l�[��
1705 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1706 _unlink(buf);
1707 rename(filename, buf);
1708
1709 error2:
1710 _unlink(filename);
1711
1712 finish_read_host_files(pvar, 0);
1713
1714 // ���������������������������B
1715 key_init(&key);
1716 }
1717 }
1718
1719
1720 //
1721 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1722 // ���[�U���m�F�������B
1723 // TODO: finger print���\�����s���B
1724 // (2006.3.25 yutaka)
1725 //
1726 static INT_PTR CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1727 LPARAM lParam)
1728 {
1729 PTInstVar pvar;
1730 char uimsg[MAX_UIMSG];
1731
1732 switch (msg) {
1733 case WM_INITDIALOG:
1734 pvar = (PTInstVar) lParam;
1735 pvar->hosts_state.hosts_dialog = dlg;
1736 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1737
1738 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1739 GetWindowText(dlg, uimsg, sizeof(uimsg));
1740 UTIL_get_lang_msg("DLG_UNKNOWNHOST_TITLE", pvar, uimsg);
1741 SetWindowText(dlg, pvar->ts->UIMsg);
1742 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1743 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING", pvar, uimsg);
1744 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1745 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1746 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING2", pvar, uimsg);
1747 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1748 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1749 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1750 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1751 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
1752 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FP_HASH_ALGORITHM", pvar, uimsg);
1753 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
1754 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1755 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1756 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1757 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1758 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1759 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1760 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1761 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1762 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1763
1764 switch (pvar->dns_key_check) {
1765 case DNS_VERIFY_NOTFOUND:
1766 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1767 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1768 break;
1769 case DNS_VERIFY_MATCH:
1770 case DNS_VERIFY_AUTH_MATCH:
1771 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1772 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1773 break;
1774 case DNS_VERIFY_MISMATCH:
1775 case DNS_VERIFY_AUTH_MISMATCH:
1776 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1777 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1778 break;
1779 case DNS_VERIFY_DIFFERENTTYPE:
1780 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1781 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1782 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1783 break;
1784 }
1785
1786 switch (pvar->dns_key_check) {
1787 case DNS_VERIFY_MATCH:
1788 case DNS_VERIFY_MISMATCH:
1789 case DNS_VERIFY_DIFFERENTTYPE:
1790 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1791 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1792 break;
1793 case DNS_VERIFY_AUTH_MATCH:
1794 case DNS_VERIFY_AUTH_MISMATCH:
1795 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1796 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1797 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1798 break;
1799 }
1800
1801 init_hosts_dlg(pvar, dlg);
1802 // add host check box���`�F�b�N���f�t�H���g������������
1803 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1804
1805 CenterWindow(dlg, GetParent(dlg));
1806
1807 return TRUE; /* because we do not set the focus */
1808
1809 case WM_COMMAND:
1810 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1811
1812 switch (LOWORD(wParam)) {
1813 case IDC_CONTINUE:
1814 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1815 if (!pvar->cv->Ready) {
1816 goto canceled;
1817 }
1818
1819 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1820 add_host_key(pvar);
1821 }
1822
1823 /*
1824 * known_hosts�_�C�A���O���������������~��������
1825 * SSH�T�[�o�����l�S�V�G�[�V���������J�������B
1826 */
1827 HOSTS_resume_session_after_known_hosts(pvar);
1828
1829 pvar->hosts_state.hosts_dialog = NULL;
1830
1831 EndDialog(dlg, 1);
1832 return TRUE;
1833
1834 case IDCANCEL: /* kill the connection */
1835 canceled:
1836 /*
1837 * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
1838 */
1839 HOSTS_cancel_session_after_known_hosts(pvar);
1840
1841 pvar->hosts_state.hosts_dialog = NULL;
1842 notify_closed_connection(pvar, "authentication cancelled");
1843 EndDialog(dlg, 0);
1844 return TRUE;
1845
1846 case IDCLOSE:
1847 /*
1848 * known_hosts�����T�[�o�������l�b�g���[�N���f�����������A
1849 * �_�C�A���O�������������B
1850 */
1851 HOSTS_cancel_session_after_known_hosts(pvar);
1852
1853 pvar->hosts_state.hosts_dialog = NULL;
1854 EndDialog(dlg, 0);
1855 return TRUE;
1856
1857 case IDC_FP_HASH_ALG_MD5:
1858 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
1859 return TRUE;
1860
1861 case IDC_FP_HASH_ALG_SHA256:
1862 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
1863 return TRUE;
1864
1865 default:
1866 return FALSE;
1867 }
1868
1869 case WM_DPICHANGED:
1870 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1871 if (pvar->hFontFixed != NULL) {
1872 DeleteObject(pvar->hFontFixed);
1873 }
1874 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
1875 if (pvar->hFontFixed != NULL) {
1876 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
1877 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
1878 }
1879 return FALSE;
1880
1881 case WM_DESTROY:
1882 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1883 if (pvar->hFontFixed != NULL) {
1884 DeleteObject(pvar->hFontFixed);
1885 pvar->hFontFixed = NULL;
1886 }
1887 return FALSE;
1888
1889 default:
1890 return FALSE;
1891 }
1892 }
1893
1894 //
1895 // �u�����������m�F�_�C�A���O������
1896 //
1897 static INT_PTR CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1898 LPARAM lParam)
1899 {
1900 PTInstVar pvar;
1901 char uimsg[MAX_UIMSG];
1902
1903 switch (msg) {
1904 case WM_INITDIALOG:
1905 pvar = (PTInstVar) lParam;
1906 pvar->hosts_state.hosts_dialog = dlg;
1907 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1908
1909 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1910 GetWindowText(dlg, uimsg, sizeof(uimsg));
1911 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
1912 SetWindowText(dlg, pvar->ts->UIMsg);
1913 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1914 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
1915 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1916 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1917 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
1918 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1919 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1920 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
1921 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1922 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
1923 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FP_HASH_ALGORITHM", pvar, uimsg);
1924 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
1925 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1926 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
1927 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1928 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1929 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1930 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1931 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1932 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1933 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1934
1935 switch (pvar->dns_key_check) {
1936 case DNS_VERIFY_NOTFOUND:
1937 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1938 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1939 break;
1940 case DNS_VERIFY_MATCH:
1941 case DNS_VERIFY_AUTH_MATCH:
1942 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1943 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1944 break;
1945 case DNS_VERIFY_MISMATCH:
1946 case DNS_VERIFY_AUTH_MISMATCH:
1947 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1948 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1949 break;
1950 case DNS_VERIFY_DIFFERENTTYPE:
1951 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1952 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1953 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1954 break;
1955 }
1956
1957 switch (pvar->dns_key_check) {
1958 case DNS_VERIFY_MATCH:
1959 case DNS_VERIFY_MISMATCH:
1960 case DNS_VERIFY_DIFFERENTTYPE:
1961 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1962 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1963 break;
1964 case DNS_VERIFY_AUTH_MATCH:
1965 case DNS_VERIFY_AUTH_MISMATCH:
1966 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1967 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1968 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1969 break;
1970 }
1971
1972 init_hosts_dlg(pvar, dlg);
1973 CenterWindow(dlg, GetParent(dlg));
1974 // �f�t�H���g���`�F�b�N����������
1975 return TRUE; /* because we do not set the focus */
1976
1977 case WM_COMMAND:
1978 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1979
1980 switch (LOWORD(wParam)) {
1981 case IDC_CONTINUE:
1982 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1983 if (!pvar->cv->Ready) {
1984 goto canceled;
1985 }
1986
1987 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1988 add_host_key(pvar);
1989 delete_different_key(pvar);
1990 }
1991
1992 /*
1993 * known_hosts�_�C�A���O���������������~��������
1994 * SSH�T�[�o�����l�S�V�G�[�V���������J�������B
1995 */
1996 HOSTS_resume_session_after_known_hosts(pvar);
1997
1998 pvar->hosts_state.hosts_dialog = NULL;
1999
2000 EndDialog(dlg, 1);
2001 return TRUE;
2002
2003 case IDCANCEL: /* kill the connection */
2004 canceled:
2005 /*
2006 * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
2007 */
2008 HOSTS_cancel_session_after_known_hosts(pvar);
2009
2010 pvar->hosts_state.hosts_dialog = NULL;
2011 notify_closed_connection(pvar, "authentication cancelled");
2012 EndDialog(dlg, 0);
2013 return TRUE;
2014
2015 case IDCLOSE:
2016 /*
2017 * known_hosts�����T�[�o�������l�b�g���[�N���f�����������A
2018 * �_�C�A���O�������������B
2019 */
2020 HOSTS_cancel_session_after_known_hosts(pvar);
2021
2022 pvar->hosts_state.hosts_dialog = NULL;
2023 EndDialog(dlg, 0);
2024 return TRUE;
2025
2026 case IDC_FP_HASH_ALG_MD5:
2027 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2028 return TRUE;
2029
2030 case IDC_FP_HASH_ALG_SHA256:
2031 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2032 return TRUE;
2033
2034 default:
2035 return FALSE;
2036 }
2037
2038 case WM_DPICHANGED:
2039 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2040 if (pvar->hFontFixed != NULL) {
2041 DeleteObject(pvar->hFontFixed);
2042 }
2043 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
2044 if (pvar->hFontFixed != NULL) {
2045 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
2046 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
2047 }
2048 return FALSE;
2049
2050 case WM_DESTROY:
2051 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2052 if (pvar->hFontFixed != NULL) {
2053 DeleteObject(pvar->hFontFixed);
2054 pvar->hFontFixed = NULL;
2055 }
2056 return FALSE;
2057
2058 default:
2059 return FALSE;
2060 }
2061 }
2062
2063 //
2064 // �����z�X�g�����`�����������������m�F�_�C�A���O������
2065 //
2066 static INT_PTR CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2067 LPARAM lParam)
2068 {
2069 PTInstVar pvar;
2070 char uimsg[MAX_UIMSG];
2071
2072 switch (msg) {
2073 case WM_INITDIALOG:
2074 pvar = (PTInstVar) lParam;
2075 pvar->hosts_state.hosts_dialog = dlg;
2076 SetWindowLongPtr(dlg, DWLP_USER, lParam);
2077
2078 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2079 GetWindowText(dlg, uimsg, sizeof(uimsg));
2080 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
2081 SetWindowText(dlg, pvar->ts->UIMsg);
2082 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
2083 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
2084 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2085 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2086 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
2087 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2088 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2089 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
2090 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2091 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2092 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FP_HASH_ALGORITHM", pvar, uimsg);
2093 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2094 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2095 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
2096 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2097 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2098 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2099 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2100 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2101 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2102 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2103
2104 switch (pvar->dns_key_check) {
2105 case DNS_VERIFY_NOTFOUND:
2106 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2107 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2108 break;
2109 case DNS_VERIFY_MATCH:
2110 case DNS_VERIFY_AUTH_MATCH:
2111 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2112 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2113 break;
2114 case DNS_VERIFY_MISMATCH:
2115 case DNS_VERIFY_AUTH_MISMATCH:
2116 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2117 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2118 break;
2119 case DNS_VERIFY_DIFFERENTTYPE:
2120 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2121 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2122 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2123 break;
2124 }
2125
2126 switch (pvar->dns_key_check) {
2127 case DNS_VERIFY_MATCH:
2128 case DNS_VERIFY_MISMATCH:
2129 case DNS_VERIFY_DIFFERENTTYPE:
2130 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2131 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2132 break;
2133 case DNS_VERIFY_AUTH_MATCH:
2134 case DNS_VERIFY_AUTH_MISMATCH:
2135 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2136 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2137 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2138 break;
2139 }
2140
2141 init_hosts_dlg(pvar, dlg);
2142 CenterWindow(dlg, GetParent(dlg));
2143 // add host check box ���f�t�H���g�� off ������
2144 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
2145
2146 return TRUE; /* because we do not set the focus */
2147
2148 case WM_COMMAND:
2149 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2150
2151 switch (LOWORD(wParam)) {
2152 case IDC_CONTINUE:
2153 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2154 if (!pvar->cv->Ready) {
2155 goto canceled;
2156 }
2157
2158 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2159 add_host_key(pvar);
2160 }
2161
2162 /*
2163 * known_hosts�_�C�A���O���������������~��������
2164 * SSH�T�[�o�����l�S�V�G�[�V���������J�������B
2165 */
2166 HOSTS_resume_session_after_known_hosts(pvar);
2167
2168 pvar->hosts_state.hosts_dialog = NULL;
2169
2170 EndDialog(dlg, 1);
2171 return TRUE;
2172
2173 case IDCANCEL: /* kill the connection */
2174 canceled:
2175 /*
2176 * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
2177 */
2178 HOSTS_cancel_session_after_known_hosts(pvar);
2179
2180 pvar->hosts_state.hosts_dialog = NULL;
2181 notify_closed_connection(pvar, "authentication cancelled");
2182 EndDialog(dlg, 0);
2183 return TRUE;
2184
2185 case IDCLOSE:
2186 /*
2187 * known_hosts�����T�[�o�������l�b�g���[�N���f�����������A
2188 * �_�C�A���O�������������B
2189 */
2190 HOSTS_cancel_session_after_known_hosts(pvar);
2191
2192 pvar->hosts_state.hosts_dialog = NULL;
2193 EndDialog(dlg, 0);
2194 return TRUE;
2195
2196 case IDC_FP_HASH_ALG_MD5:
2197 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2198 return TRUE;
2199
2200 case IDC_FP_HASH_ALG_SHA256:
2201 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2202 return TRUE;
2203
2204 default:
2205 return FALSE;
2206 }
2207
2208 case WM_DPICHANGED:
2209 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2210 if (pvar->hFontFixed != NULL) {
2211 DeleteObject(pvar->hFontFixed);
2212 }
2213 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
2214 if (pvar->hFontFixed != NULL) {
2215 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
2216 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
2217 }
2218 return FALSE;
2219
2220 case WM_DESTROY:
2221 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2222 if (pvar->hFontFixed != NULL) {
2223 DeleteObject(pvar->hFontFixed);
2224 pvar->hFontFixed = NULL;
2225 }
2226 return FALSE;
2227
2228 default:
2229 return FALSE;
2230 }
2231 }
2232
2233 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
2234 {
2235 if (pvar->hosts_state.hosts_dialog == NULL) {
2236 /* known_hosts�������������AID_SSHASYNCMESSAGEBOX ���g����
2237 * MessageBox ���\�������������A�I�[�i�[����(no owner)�����������A
2238 * MessageBox ��Tera Term�������B���������������B
2239 * ���������� GetActiveWindow() �������o�����Aknown_hosts�_�C�A���O��
2240 * �I�[�i�[�� MessageBox ���������ATera Term�������B�����������B
2241 * �������Aknown_hosts�_�C�A���O���I�[�i�[������ Tera Term ���w������
2242 * �����������B
2243 */
2244 HWND cur_active = NULL;
2245
2246 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
2247 cur_active != NULL ? cur_active : wnd,
2248 hosts_add_dlg_proc, (LPARAM) pvar);
2249 }
2250 }
2251
2252 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
2253 {
2254 if (pvar->hosts_state.hosts_dialog == NULL) {
2255 /* known_hosts�������������AID_SSHASYNCMESSAGEBOX ���g����
2256 * MessageBox ���\�������������A�I�[�i�[����(no owner)�����������A
2257 * MessageBox ��Tera Term�������B���������������B
2258 * ���������� GetActiveWindow() �������o�����Aknown_hosts�_�C�A���O��
2259 * �I�[�i�[�� MessageBox ���������ATera Term�������B�����������B
2260 * �������Aknown_hosts�_�C�A���O���I�[�i�[������ Tera Term ���w������
2261 * �����������B
2262 */
2263 HWND cur_active = NULL;
2264
2265 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
2266 cur_active != NULL ? cur_active : wnd,
2267 hosts_replace_dlg_proc, (LPARAM) pvar);
2268 }
2269 }
2270
2271 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
2272 {
2273 if (pvar->hosts_state.hosts_dialog == NULL) {
2274 /* known_hosts�������������AID_SSHASYNCMESSAGEBOX ���g����
2275 * MessageBox ���\�������������A�I�[�i�[����(no owner)�����������A
2276 * MessageBox ��Tera Term�������B���������������B
2277 * ���������� GetActiveWindow() �������o�����Aknown_hosts�_�C�A���O��
2278 * �I�[�i�[�� MessageBox ���������ATera Term�������B�����������B
2279 * �������Aknown_hosts�_�C�A���O���I�[�i�[������ Tera Term ���w������
2280 * �����������B
2281 */
2282 HWND cur_active = NULL;
2283
2284 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2285 cur_active != NULL ? cur_active : wnd,
2286 hosts_add2_dlg_proc, (LPARAM) pvar);
2287 }
2288 }
2289
2290 /*
2291 * �T�[�o�����������������z�X�g���J�������������`�F�b�N���A
2292 * �K�v�������� known_hosts �_�C�A���O�������o���B
2293 *
2294 * hostname: ���������z�X�g��
2295 * tcpport: �������|�[�g����
2296 * key: �T�[�o���������J��
2297 *
2298 * return:
2299 * TRUE: known_hosts�_�C�A���O�������o�����s�v
2300 * FALSE: known_hosts�_�C�A���O�������o����
2301 *
2302 */
2303 BOOL HOSTS_check_host_key(PTInstVar pvar, char *hostname, unsigned short tcpport, Key *key)
2304 {
2305 int found_different_key = 0, found_different_type_key = 0;
2306 Key key2; // known_hosts���o�^������������
2307 DWORD id;
2308
2309 pvar->dns_key_check = DNS_VERIFY_NONE;
2310
2311 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
2312 if (pvar->hosts_state.prefetched_hostname != NULL
2313 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
2314 && HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key) == 1) {
2315
2316 // ���������������B
2317 return TRUE;
2318 }
2319
2320 // �������������������������A�������_���t�@�C��������������
2321 memset(&key2, 0, sizeof(key2));
2322 if (begin_read_host_files(pvar, 0)) {
2323 do {
2324 if (!read_host_key(pvar, hostname, tcpport, 0, 0, &key2)) {
2325 break;
2326 }
2327
2328 if (key2.type != KEY_UNSPEC) {
2329 int match = HOSTS_compare_public_key(&key2, key);
2330 if (match == 1) {
2331 finish_read_host_files(pvar, 0);
2332 // ���������G���g�����Q�������A���v�����L�[�������������������B
2333 // About TTSSH �_�C�A���O�����\�����������A�������������������B
2334 key_copy(&pvar->hosts_state.hostkey, key);
2335
2336 return TRUE;
2337 }
2338 else if (match == 0) {
2339 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2340 found_different_key = 1;
2341 }
2342 else {
2343 // �L�[���`������������
2344 found_different_type_key = 1;
2345 }
2346 }
2347 } while (key2.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2348
2349 key_init(&key2);
2350 finish_read_host_files(pvar, 0);
2351 }
2352
2353 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2354 key_copy(&pvar->hosts_state.hostkey, key);
2355
2356 free(pvar->hosts_state.prefetched_hostname);
2357 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2358
2359 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2360 if (pvar->nocheck_known_hosts == TRUE) {
2361 // ���������������B
2362 return TRUE;
2363 }
2364
2365 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2366 pvar->dns_key_check = verify_hostkey_dns(pvar, hostname, key);
2367 }
2368
2369 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
2370 // �������K�v�����������A�����R�[�������X�����B
2371 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
2372 // (2007.10.1 yutaka)
2373 /*
2374 * known_hosts�_�C�A���O�����������\�����������������������B
2375 * known_hosts�_�C�A���O���\�������������������A�T�[�o�������f���s�����A
2376 * TTXCloseTCP�������o�����ATTSSH�����\�[�X�������������������B
2377 * SSH�n���h����������known_hosts�_�C�A���O���o�����~���������������A
2378 * �������J�����s���A�N�Z�X���������B
2379 * (2019.9.3 yutaka)
2380 */
2381 if (found_different_key) {
2382 // TTXProcessCommand ���� HOSTS_do_different_key_dialog() �������o���B
2383 id = ID_SSHDIFFERENTKEY;
2384 }
2385 else if (found_different_type_key) {
2386 // TTXProcessCommand ���� HOSTS_do_different_type_key_dialog() �������o���B
2387 id = ID_SSHDIFFERENT_TYPE_KEY;
2388 }
2389 else {
2390 // TTXProcessCommand ���� HOSTS_do_unknown_host_dialog() �������o���B
2391 id = ID_SSHUNKNOWNHOST;
2392 }
2393
2394 PostMessage(pvar->NotificationWindow, WM_COMMAND, id, 0);
2395
2396 logprintf(LOG_LEVEL_INFO, "Calling known_hosts dialog...(%s)",
2397 id == ID_SSHDIFFERENTKEY ? "SSHDIFFERENTKEY" :
2398 id == ID_SSHDIFFERENT_TYPE_KEY ? "SSHDIFFERENT_TYPE_KEY" : "SSHUNKNOWNHOST"
2399 );
2400
2401 return FALSE;
2402 }
2403
2404 /*
2405 * known_hosts�_�C�A���O�����[�U���F���ASSH�T�[�o�����l�S�V�G�[�V���������J�����B
2406 */
2407 BOOL HOSTS_resume_session_after_known_hosts(PTInstVar pvar)
2408 {
2409 enum ssh_kex_known_hosts type;
2410 int ret = FALSE;
2411
2412 type = pvar->contents_after_known_hosts.kex_type;
2413 if (type == SSH1_PUBLIC_KEY_KNOWN_HOSTS) {
2414 ret = handle_server_public_key_after_known_hosts(pvar);
2415
2416 } else if (type == SSH2_DH_KEX_REPLY_KNOWN_HOSTS) {
2417 ret = handle_SSH2_dh_kex_reply_after_known_hosts(pvar);
2418
2419 } else if (type == SSH2_DH_GEX_REPLY_KNOWN_HOSTS) {
2420 ret = handle_SSH2_dh_gex_reply_after_known_hosts(pvar);
2421
2422 } else if (type == SSH2_ECDH_KEX_REPLY_KNOWN_HOSTS) {
2423 ret = handle_SSH2_ecdh_kex_reply_after_known_hosts(pvar);
2424
2425 }
2426
2427 return (ret);
2428 }
2429
2430 /*
2431 * known_hosts�_�C�A���O��SSH�������L�����Z������
2432 */
2433 void HOSTS_cancel_session_after_known_hosts(PTInstVar pvar)
2434 {
2435 enum ssh_kex_known_hosts type;
2436
2437 type = pvar->contents_after_known_hosts.kex_type;
2438 if (type != NONE_KNOWN_HOSTS) {
2439 handle_SSH2_canel_reply_after_known_hosts(pvar);
2440 }
2441
2442 return;
2443 }
2444
2445
2446 void HOSTS_notify_disconnecting(PTInstVar pvar)
2447 {
2448 if (pvar->hosts_state.hosts_dialog != NULL) {
2449 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
2450 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
2451 EnableWindow(pvar->NotificationWindow, TRUE);
2452 }
2453 }
2454
2455 // TCP�Z�b�V�������N���[�Y�����������Aknown_hosts�_�C�A���O���������������w�����o���B
2456 // HOSTS_notify_disconnecting()�����������A�_�C�A���O���������������A
2457 // SSH�T�[�o�����m���o�������B
2458 void HOSTS_notify_closing_on_exit(PTInstVar pvar)
2459 {
2460 if (pvar->hosts_state.hosts_dialog != NULL) {
2461 logprintf(LOG_LEVEL_INFO, "%s: Notify closing message to the known_hosts dialog.", __FUNCTION__);
2462 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCLOSE, 0);
2463 }
2464 }
2465
2466 void HOSTS_end(PTInstVar pvar)
2467 {
2468 int i;
2469
2470 free(pvar->hosts_state.prefetched_hostname);
2471 key_init(&pvar->hosts_state.hostkey);
2472
2473 if (pvar->hosts_state.file_names != NULL) {
2474 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
2475 free(pvar->hosts_state.file_names[i]);
2476 }
2477 free(pvar->hosts_state.file_names);
2478 }
2479 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26