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 6998 - (show annotations) (download) (as text)
Wed Nov 29 22:54:33 2017 UTC (6 years, 4 months ago) by maya
File MIME type: text/x-csrc
File size: 68123 byte(s)
[About TTSSH] ダイアログに正しくないサーバホスト鍵の指紋が表示されることがある問題を修正

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

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