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 10615 - (show annotations) (download) (as text)
Wed Mar 1 14:18:31 2023 UTC (13 months, 1 week ago) by zmatsuo
File MIME type: text/x-csrc
File size: 67482 byte(s)
ttxssh内 lngファイル名変数を ANSI版から Unicode 版へ切り替え

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

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