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

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