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

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