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

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