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 8316 - (show annotations) (download) (as text)
Wed Oct 16 13:19:25 2019 UTC (4 years, 5 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 68214 byte(s)
- TTSSHとTTProxyを OpenSSL 1.1.1 に対応した。
  ※OpenSSL 1.0.2ではビルドできません
- Win32 APIのWindows依存チェックツール(installer/checksymbol)を追加した。

branches/openssl_1_1_1_v3からリビジョン8258をマージ:
/branches/openssl_1_1_1_v2 ブランチの r7785 - r8256 をマージした。


........

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

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