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 7889 - (show annotations) (download) (as text)
Thu Jul 25 10:36:55 2019 UTC (4 years, 8 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 65648 byte(s)
SSH1: 接続先のポート番号が22以外で、新規にknown_hostsファイルへホスト鍵を
書き込む時、アプリが落ちることがある問題を修正した。

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

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