Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/hosts.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9210 - (show annotations) (download) (as text)
Sat Apr 17 08:36:59 2021 UTC (2 years, 11 months ago) by nmaya
File MIME type: text/x-csrc
File size: 69262 byte(s)
ファイルを分割・コードを移動・関数名を整理・新しい OpenSSH からインポート

- OpenSSH からインポート
  cipher-3des1.c from OpenSSH-7.5p1
  ssherr.c from OpenSSH-8.5p1
  ssherr.h from OpenSSH-8.5p1
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
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_hostkey_type_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_hostkey_type_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_ssh2_hostkey_type_name_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_ssh2_hostkey_type_name_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_ssh2_hostkey_type_name_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_ssh2_hostkey_type_name_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 int fd;
1375 int amount_written = 0;
1376 int close_result;
1377 int data_index = 0;
1378 char *newfiledata = NULL;
1379 int ret;
1380 struct _stat fileStat;
1381 long newFilePos = 0, totalSize;
1382
1383 // known_hosts�t�@�C���T�C�Y�����������B
1384 get_teraterm_dir_relative_name(filename, sizeof(filename), name);
1385 ret = _stat(filename, &fileStat);
1386 if (ret != 0) {
1387 // error
1388 goto error;
1389 }
1390 // �t�@�C���f�[�^�����������m�������B
1391 totalSize = fileStat.st_size;
1392 newfiledata = malloc(totalSize);
1393 if (newfiledata == NULL) {
1394 // error
1395 goto error;
1396 }
1397
1398
1399 // �t�@�C��������������
1400 memset(&key, 0, sizeof(key));
1401 begin_read_host_files(pvar, 0);
1402 do {
1403 int host_index = 0;
1404 int matched = 0;
1405 int keybits = 0;
1406 char *data;
1407 int do_write = 0;
1408 length = amount_written = 0;
1409
1410 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1411 break;
1412 }
1413
1414 if (data_index == pvar->hosts_state.file_data_index) {
1415 // index ���i������ == ��������������
1416 break;
1417 }
1418
1419 data = pvar->hosts_state.file_data + data_index;
1420 host_index = eat_spaces(data);
1421
1422 if (data[host_index] == '#') {
1423 do_write = 1;
1424 }
1425 else {
1426 // �z�X�g������
1427 host_index--;
1428 do {
1429 int negated;
1430 int bracketed;
1431 char *end_bracket;
1432 int host_matched = 0;
1433 unsigned short keyfile_port = 22;
1434
1435 host_index++;
1436 negated = data[host_index] == '!';
1437
1438 if (negated) {
1439 host_index++;
1440 bracketed = data[host_index] == '[';
1441 if (bracketed) {
1442 end_bracket = strstr(data + host_index + 1, "]:");
1443 if (end_bracket != NULL) {
1444 *end_bracket = ' ';
1445 host_index++;
1446 }
1447 }
1448 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1449 if (bracketed && end_bracket != NULL) {
1450 *end_bracket = ']';
1451 keyfile_port = atoi(end_bracket + 2);
1452 }
1453 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1454 matched = 0;
1455 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1456 host_index--;
1457 do {
1458 host_index++;
1459 host_index += eat_to_end_of_pattern(data + host_index);
1460 } while (data[host_index] == ',');
1461 break;
1462 }
1463 }
1464 else {
1465 bracketed = data[host_index] == '[';
1466 if (bracketed) {
1467 end_bracket = strstr(data + host_index + 1, "]:");
1468 if (end_bracket != NULL) {
1469 *end_bracket = ' ';
1470 host_index++;
1471 }
1472 }
1473 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1474 if (bracketed && end_bracket != NULL) {
1475 *end_bracket = ']';
1476 keyfile_port = atoi(end_bracket + 2);
1477 }
1478 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1479 matched = 1;
1480 }
1481 }
1482 host_index += eat_to_end_of_pattern(data + host_index);
1483 } while (data[host_index] == ',');
1484
1485 // �z�X�g������������
1486 if (!matched) {
1487 do_write = 1;
1488 }
1489 // �z�X�g��������
1490 else {
1491 // �����`�������� or ���v�����L�[
1492 if (HOSTS_compare_public_key(&pvar->hosts_state.hostkey, &key) != 0) {
1493 do_write = 1;
1494 }
1495 // �����`�������������v�������L�[���X�L�b�v������
1496 }
1497 }
1498
1499 // ������������
1500 if (do_write) {
1501 length = pvar->hosts_state.file_data_index - data_index;
1502
1503 if ((newFilePos + length) >= totalSize) {
1504 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1505 "An error occurred while trying to write the host key.\n"
1506 "The host key could not be written.");
1507 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1508 goto error;
1509 }
1510
1511 memcpy(newfiledata + newFilePos,
1512 pvar->hosts_state.file_data + data_index,
1513 length);
1514 newFilePos += length;
1515
1516 }
1517 data_index = pvar->hosts_state.file_data_index;
1518 } while (1); // ������������
1519
1520 finish_read_host_files(pvar, 0);
1521
1522 // ���������������������������B
1523 key_init(&key);
1524
1525 // known_hosts�t�@�C�����V�����t�@�C���f�[�^�������������B
1526 fd = _open(filename,
1527 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1528 _S_IREAD | _S_IWRITE);
1529
1530 if (fd == -1) {
1531 if (errno == EACCES) {
1532 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1533 "An error occurred while trying to write the host key.\n"
1534 "You do not have permission to write to the known-hosts file.");
1535 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1536 }
1537 else {
1538 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1539 "An error occurred while trying to write the host key.\n"
1540 "The host key could not be written.");
1541 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1542 }
1543 goto error;
1544 }
1545
1546 amount_written = _write(fd, newfiledata, newFilePos);
1547 close_result = _close(fd);
1548 if (amount_written != newFilePos || close_result == -1) {
1549 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1550 "An error occurred while trying to write the host key.\n"
1551 "The host key could not be written.");
1552 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1553 goto error;
1554 }
1555
1556 error:
1557 if (newfiledata) {
1558 free(newfiledata);
1559 }
1560
1561 }
1562 }
1563
1564
1565 void HOSTS_delete_all_hostkeys(PTInstVar pvar)
1566 {
1567 char *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 char filename[MAX_PATH];
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 get_teraterm_dir_relative_name(filename, sizeof(filename), name);
1595 ret = _stat(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 = _open(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 if (newfiledata) {
1764 free(newfiledata);
1765 }
1766
1767 }
1768 }
1769
1770
1771 //
1772 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1773 // ���[�U���m�F�������B
1774 // TODO: finger print���\�����s���B
1775 // (2006.3.25 yutaka)
1776 //
1777 static INT_PTR CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1778 LPARAM lParam)
1779 {
1780 const static DlgTextInfo text_info[] = {
1781 { 0, "DLG_UNKNOWNHOST_TITLE" },
1782 { IDC_HOSTWARNING, "DLG_UNKNOWNHOST_WARNING" },
1783 { IDC_HOSTWARNING2, "DLG_UNKNOWNHOST_WARNING2" },
1784 { IDC_HOSTFINGERPRINT, "DLG_UNKNOWNHOST_FINGERPRINT" },
1785 { IDC_FP_HASH_ALG, "DLG_UNKNOWNHOST_FP_HASH_ALGORITHM" },
1786 { IDC_ADDTOKNOWNHOSTS, "DLG_UNKNOWNHOST_ADD" },
1787 { IDC_CONTINUE, "BTN_CONTINUE" },
1788 { IDCANCEL, "BTN_DISCONNECT" },
1789 };
1790 PTInstVar pvar;
1791
1792 switch (msg) {
1793 case WM_INITDIALOG:
1794 pvar = (PTInstVar) lParam;
1795 pvar->hosts_state.hosts_dialog = dlg;
1796 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1797
1798 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1799 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
1800
1801 switch (pvar->dns_key_check) {
1802 case DNS_VERIFY_NOTFOUND:
1803 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1804 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1805 break;
1806 case DNS_VERIFY_MATCH:
1807 case DNS_VERIFY_AUTH_MATCH:
1808 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1809 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1810 break;
1811 case DNS_VERIFY_MISMATCH:
1812 case DNS_VERIFY_AUTH_MISMATCH:
1813 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1814 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1815 break;
1816 case DNS_VERIFY_DIFFERENTTYPE:
1817 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1818 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1819 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1820 break;
1821 }
1822
1823 switch (pvar->dns_key_check) {
1824 case DNS_VERIFY_MATCH:
1825 case DNS_VERIFY_MISMATCH:
1826 case DNS_VERIFY_DIFFERENTTYPE:
1827 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1828 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1829 break;
1830 case DNS_VERIFY_AUTH_MATCH:
1831 case DNS_VERIFY_AUTH_MISMATCH:
1832 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1833 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1834 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1835 break;
1836 }
1837
1838 init_hosts_dlg(pvar, dlg);
1839 // add host check box���`�F�b�N���f�t�H���g������������
1840 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1841
1842 CenterWindow(dlg, GetParent(dlg));
1843
1844 return TRUE; /* because we do not set the focus */
1845
1846 case WM_COMMAND:
1847 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1848
1849 switch (LOWORD(wParam)) {
1850 case IDC_CONTINUE:
1851 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1852 if (!pvar->cv->Ready) {
1853 goto canceled;
1854 }
1855
1856 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1857 add_host_key(pvar);
1858 }
1859
1860 /*
1861 * known_hosts�_�C�A���O���������������~��������
1862 * SSH�T�[�o�����l�S�V�G�[�V���������J�������B
1863 */
1864 HOSTS_resume_session_after_known_hosts(pvar);
1865
1866 pvar->hosts_state.hosts_dialog = NULL;
1867
1868 EndDialog(dlg, 1);
1869 return TRUE;
1870
1871 case IDCANCEL: /* kill the connection */
1872 canceled:
1873 /*
1874 * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
1875 */
1876 HOSTS_cancel_session_after_known_hosts(pvar);
1877
1878 pvar->hosts_state.hosts_dialog = NULL;
1879 notify_closed_connection(pvar, "authentication cancelled");
1880 EndDialog(dlg, 0);
1881 return TRUE;
1882
1883 case IDCLOSE:
1884 /*
1885 * known_hosts�����T�[�o�������l�b�g���[�N���f�����������A
1886 * �_�C�A���O�������������B
1887 */
1888 HOSTS_cancel_session_after_known_hosts(pvar);
1889
1890 pvar->hosts_state.hosts_dialog = NULL;
1891 EndDialog(dlg, 0);
1892 return TRUE;
1893
1894 case IDC_FP_HASH_ALG_MD5:
1895 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
1896 return TRUE;
1897
1898 case IDC_FP_HASH_ALG_SHA256:
1899 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
1900 return TRUE;
1901
1902 default:
1903 return FALSE;
1904 }
1905
1906 case WM_DPICHANGED:
1907 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1908 if (pvar->hFontFixed != NULL) {
1909 DeleteObject(pvar->hFontFixed);
1910 }
1911 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
1912 if (pvar->hFontFixed != NULL) {
1913 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
1914 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
1915 }
1916 return FALSE;
1917
1918 case WM_DESTROY:
1919 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1920 if (pvar->hFontFixed != NULL) {
1921 DeleteObject(pvar->hFontFixed);
1922 pvar->hFontFixed = NULL;
1923 }
1924 return FALSE;
1925
1926 default:
1927 return FALSE;
1928 }
1929 }
1930
1931 //
1932 // �u�����������m�F�_�C�A���O������
1933 //
1934 static INT_PTR CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1935 LPARAM lParam)
1936 {
1937 const static DlgTextInfo text_info[] = {
1938 { 0, "DLG_UNKNOWNHOST_TITLE" },
1939 { IDC_HOSTWARNING, "DLG_DIFFERENTKEY_WARNING" },
1940 { IDC_HOSTWARNING2, "DLG_DIFFERENTKEY_WARNING2" },
1941 { IDC_HOSTFINGERPRINT, "DLG_DIFFERENTKEY_FINGERPRINT" },
1942 { IDC_FP_HASH_ALG, "DLG_DIFFERENTKEY_FP_HASH_ALGORITHM" },
1943 { IDC_ADDTOKNOWNHOSTS, "DLG_DIFFERENTKEY_REPLACE" },
1944 { IDC_CONTINUE, "BTN_CONTINUE" },
1945 { IDCANCEL, "BTN_DISCONNECT" },
1946 };
1947 PTInstVar pvar;
1948
1949 switch (msg) {
1950 case WM_INITDIALOG:
1951 pvar = (PTInstVar) lParam;
1952 pvar->hosts_state.hosts_dialog = dlg;
1953 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1954
1955 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1956 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
1957
1958 switch (pvar->dns_key_check) {
1959 case DNS_VERIFY_NOTFOUND:
1960 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1961 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1962 break;
1963 case DNS_VERIFY_MATCH:
1964 case DNS_VERIFY_AUTH_MATCH:
1965 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1966 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1967 break;
1968 case DNS_VERIFY_MISMATCH:
1969 case DNS_VERIFY_AUTH_MISMATCH:
1970 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1971 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1972 break;
1973 case DNS_VERIFY_DIFFERENTTYPE:
1974 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1975 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1976 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1977 break;
1978 }
1979
1980 switch (pvar->dns_key_check) {
1981 case DNS_VERIFY_MATCH:
1982 case DNS_VERIFY_MISMATCH:
1983 case DNS_VERIFY_DIFFERENTTYPE:
1984 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1985 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1986 break;
1987 case DNS_VERIFY_AUTH_MATCH:
1988 case DNS_VERIFY_AUTH_MISMATCH:
1989 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1990 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1991 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1992 break;
1993 }
1994
1995 init_hosts_dlg(pvar, dlg);
1996 CenterWindow(dlg, GetParent(dlg));
1997 // �f�t�H���g���`�F�b�N����������
1998 return TRUE; /* because we do not set the focus */
1999
2000 case WM_COMMAND:
2001 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2002
2003 switch (LOWORD(wParam)) {
2004 case IDC_CONTINUE:
2005 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2006 if (!pvar->cv->Ready) {
2007 goto canceled;
2008 }
2009
2010 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2011 add_host_key(pvar);
2012 delete_different_key(pvar);
2013 }
2014
2015 /*
2016 * known_hosts�_�C�A���O���������������~��������
2017 * SSH�T�[�o�����l�S�V�G�[�V���������J�������B
2018 */
2019 HOSTS_resume_session_after_known_hosts(pvar);
2020
2021 pvar->hosts_state.hosts_dialog = NULL;
2022
2023 EndDialog(dlg, 1);
2024 return TRUE;
2025
2026 case IDCANCEL: /* kill the connection */
2027 canceled:
2028 /*
2029 * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
2030 */
2031 HOSTS_cancel_session_after_known_hosts(pvar);
2032
2033 pvar->hosts_state.hosts_dialog = NULL;
2034 notify_closed_connection(pvar, "authentication cancelled");
2035 EndDialog(dlg, 0);
2036 return TRUE;
2037
2038 case IDCLOSE:
2039 /*
2040 * known_hosts�����T�[�o�������l�b�g���[�N���f�����������A
2041 * �_�C�A���O�������������B
2042 */
2043 HOSTS_cancel_session_after_known_hosts(pvar);
2044
2045 pvar->hosts_state.hosts_dialog = NULL;
2046 EndDialog(dlg, 0);
2047 return TRUE;
2048
2049 case IDC_FP_HASH_ALG_MD5:
2050 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2051 return TRUE;
2052
2053 case IDC_FP_HASH_ALG_SHA256:
2054 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2055 return TRUE;
2056
2057 default:
2058 return FALSE;
2059 }
2060
2061 case WM_DPICHANGED:
2062 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2063 if (pvar->hFontFixed != NULL) {
2064 DeleteObject(pvar->hFontFixed);
2065 }
2066 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
2067 if (pvar->hFontFixed != NULL) {
2068 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
2069 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
2070 }
2071 return FALSE;
2072
2073 case WM_DESTROY:
2074 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2075 if (pvar->hFontFixed != NULL) {
2076 DeleteObject(pvar->hFontFixed);
2077 pvar->hFontFixed = NULL;
2078 }
2079 return FALSE;
2080
2081 default:
2082 return FALSE;
2083 }
2084 }
2085
2086 //
2087 // �����z�X�g�����`�����������������m�F�_�C�A���O������
2088 //
2089 static INT_PTR CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2090 LPARAM lParam)
2091 {
2092 const static DlgTextInfo text_info[] = {
2093 { 0, "DLG_DIFFERENTTYPEKEY_TITLE" },
2094 { IDC_HOSTWARNING, "DLG_DIFFERENTTYPEKEY_WARNING" },
2095 { IDC_HOSTWARNING2, "DLG_DIFFERENTTYPEKEY_WARNING2" },
2096 { IDC_HOSTFINGERPRINT, "DLG_DIFFERENTTYPEKEY_FINGERPRINT" },
2097 { IDC_FP_HASH_ALG, "DLG_DIFFERENTTYPEKEY_FP_HASH_ALGORITHM" },
2098 { IDC_ADDTOKNOWNHOSTS, "DLG_DIFFERENTTYPEKEY_ADD" },
2099 { IDC_CONTINUE, "BTN_CONTINUE" },
2100 { IDCANCEL, "BTN_DISCONNECT" },
2101 };
2102 PTInstVar pvar;
2103
2104 switch (msg) {
2105 case WM_INITDIALOG:
2106 pvar = (PTInstVar) lParam;
2107 pvar->hosts_state.hosts_dialog = dlg;
2108 SetWindowLongPtr(dlg, DWLP_USER, lParam);
2109
2110 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2111 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
2112
2113 switch (pvar->dns_key_check) {
2114 case DNS_VERIFY_NOTFOUND:
2115 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2116 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2117 break;
2118 case DNS_VERIFY_MATCH:
2119 case DNS_VERIFY_AUTH_MATCH:
2120 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2121 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2122 break;
2123 case DNS_VERIFY_MISMATCH:
2124 case DNS_VERIFY_AUTH_MISMATCH:
2125 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2126 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2127 break;
2128 case DNS_VERIFY_DIFFERENTTYPE:
2129 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2130 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2131 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2132 break;
2133 }
2134
2135 switch (pvar->dns_key_check) {
2136 case DNS_VERIFY_MATCH:
2137 case DNS_VERIFY_MISMATCH:
2138 case DNS_VERIFY_DIFFERENTTYPE:
2139 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2140 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2141 break;
2142 case DNS_VERIFY_AUTH_MATCH:
2143 case DNS_VERIFY_AUTH_MISMATCH:
2144 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2145 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2146 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2147 break;
2148 }
2149
2150 init_hosts_dlg(pvar, dlg);
2151 CenterWindow(dlg, GetParent(dlg));
2152 // add host check box ���f�t�H���g�� off ������
2153 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
2154
2155 return TRUE; /* because we do not set the focus */
2156
2157 case WM_COMMAND:
2158 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2159
2160 switch (LOWORD(wParam)) {
2161 case IDC_CONTINUE:
2162 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2163 if (!pvar->cv->Ready) {
2164 goto canceled;
2165 }
2166
2167 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2168 add_host_key(pvar);
2169 }
2170
2171 /*
2172 * known_hosts�_�C�A���O���������������~��������
2173 * SSH�T�[�o�����l�S�V�G�[�V���������J�������B
2174 */
2175 HOSTS_resume_session_after_known_hosts(pvar);
2176
2177 pvar->hosts_state.hosts_dialog = NULL;
2178
2179 EndDialog(dlg, 1);
2180 return TRUE;
2181
2182 case IDCANCEL: /* kill the connection */
2183 canceled:
2184 /*
2185 * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
2186 */
2187 HOSTS_cancel_session_after_known_hosts(pvar);
2188
2189 pvar->hosts_state.hosts_dialog = NULL;
2190 notify_closed_connection(pvar, "authentication cancelled");
2191 EndDialog(dlg, 0);
2192 return TRUE;
2193
2194 case IDCLOSE:
2195 /*
2196 * known_hosts�����T�[�o�������l�b�g���[�N���f�����������A
2197 * �_�C�A���O�������������B
2198 */
2199 HOSTS_cancel_session_after_known_hosts(pvar);
2200
2201 pvar->hosts_state.hosts_dialog = NULL;
2202 EndDialog(dlg, 0);
2203 return TRUE;
2204
2205 case IDC_FP_HASH_ALG_MD5:
2206 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2207 return TRUE;
2208
2209 case IDC_FP_HASH_ALG_SHA256:
2210 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2211 return TRUE;
2212
2213 default:
2214 return FALSE;
2215 }
2216
2217 case WM_DPICHANGED:
2218 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2219 if (pvar->hFontFixed != NULL) {
2220 DeleteObject(pvar->hFontFixed);
2221 }
2222 pvar->hFontFixed = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
2223 if (pvar->hFontFixed != NULL) {
2224 SendDlgItemMessage(dlg, IDC_FP_RANDOMART, WM_SETFONT,
2225 (WPARAM)pvar->hFontFixed, MAKELPARAM(TRUE,0));
2226 }
2227 return FALSE;
2228
2229 case WM_DESTROY:
2230 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2231 if (pvar->hFontFixed != NULL) {
2232 DeleteObject(pvar->hFontFixed);
2233 pvar->hFontFixed = NULL;
2234 }
2235 return FALSE;
2236
2237 default:
2238 return FALSE;
2239 }
2240 }
2241
2242 void HOSTS_do_unknown_host_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_SSHUNKNOWNHOST),
2256 cur_active != NULL ? cur_active : wnd,
2257 hosts_add_dlg_proc, (LPARAM) pvar);
2258 }
2259 }
2260
2261 void HOSTS_do_different_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_SSHDIFFERENTKEY),
2275 cur_active != NULL ? cur_active : wnd,
2276 hosts_replace_dlg_proc, (LPARAM) pvar);
2277 }
2278 }
2279
2280 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
2281 {
2282 if (pvar->hosts_state.hosts_dialog == NULL) {
2283 /* known_hosts�������������AID_SSHASYNCMESSAGEBOX ���g����
2284 * MessageBox ���\�������������A�I�[�i�[����(no owner)�����������A
2285 * MessageBox ��Tera Term�������B���������������B
2286 * ���������� GetActiveWindow() �������o�����Aknown_hosts�_�C�A���O��
2287 * �I�[�i�[�� MessageBox ���������ATera Term�������B�����������B
2288 * �������Aknown_hosts�_�C�A���O���I�[�i�[������ Tera Term ���w������
2289 * �����������B
2290 */
2291 HWND cur_active = NULL;
2292
2293 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2294 cur_active != NULL ? cur_active : wnd,
2295 hosts_add2_dlg_proc, (LPARAM) pvar);
2296 }
2297 }
2298
2299 /*
2300 * �T�[�o�����������������z�X�g���J�������������`�F�b�N���A
2301 * �K�v�������� known_hosts �_�C�A���O�������o���B
2302 *
2303 * hostname: ���������z�X�g��
2304 * tcpport: �������|�[�g����
2305 * key: �T�[�o���������J��
2306 *
2307 * return:
2308 * TRUE: known_hosts�_�C�A���O�������o�����s�v
2309 * FALSE: known_hosts�_�C�A���O�������o����
2310 *
2311 */
2312 BOOL HOSTS_check_host_key(PTInstVar pvar, char *hostname, unsigned short tcpport, Key *key)
2313 {
2314 int found_different_key = 0, found_different_type_key = 0;
2315 Key key2; // known_hosts���o�^������������
2316 DWORD id;
2317
2318 pvar->dns_key_check = DNS_VERIFY_NONE;
2319
2320 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
2321 if (pvar->hosts_state.prefetched_hostname != NULL
2322 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
2323 && HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key) == 1) {
2324
2325 // ���������������B
2326 return TRUE;
2327 }
2328
2329 // �������������������������A�������_���t�@�C��������������
2330 memset(&key2, 0, sizeof(key2));
2331 if (begin_read_host_files(pvar, 0)) {
2332 do {
2333 if (!read_host_key(pvar, hostname, tcpport, 0, 0, &key2)) {
2334 break;
2335 }
2336
2337 if (key2.type != KEY_UNSPEC) {
2338 int match = HOSTS_compare_public_key(&key2, key);
2339 if (match == 1) {
2340 finish_read_host_files(pvar, 0);
2341 // ���������G���g�����Q�������A���v�����L�[�������������������B
2342 // About TTSSH �_�C�A���O�����\�����������A�������������������B
2343 key_copy(&pvar->hosts_state.hostkey, key);
2344
2345 return TRUE;
2346 }
2347 else if (match == 0) {
2348 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2349 found_different_key = 1;
2350 }
2351 else {
2352 // �L�[���`������������
2353 found_different_type_key = 1;
2354 }
2355 }
2356 } while (key2.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2357
2358 key_init(&key2);
2359 finish_read_host_files(pvar, 0);
2360 }
2361
2362 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2363 key_copy(&pvar->hosts_state.hostkey, key);
2364
2365 free(pvar->hosts_state.prefetched_hostname);
2366 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2367
2368 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2369 if (pvar->nocheck_known_hosts == TRUE) {
2370 // ���������������B
2371 return TRUE;
2372 }
2373
2374 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2375 pvar->dns_key_check = verify_hostkey_dns(pvar, hostname, key);
2376 }
2377
2378 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
2379 // �������K�v�����������A�����R�[�������X�����B
2380 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
2381 // (2007.10.1 yutaka)
2382 /*
2383 * known_hosts�_�C�A���O�����������\�����������������������B
2384 * known_hosts�_�C�A���O���\�������������������A�T�[�o�������f���s�����A
2385 * TTXCloseTCP�������o�����ATTSSH�����\�[�X�������������������B
2386 * SSH�n���h����������known_hosts�_�C�A���O���o�����~���������������A
2387 * �������J�����s���A�N�Z�X���������B
2388 * (2019.9.3 yutaka)
2389 */
2390 if (found_different_key) {
2391 // TTXProcessCommand ���� HOSTS_do_different_key_dialog() �������o���B
2392 id = ID_SSHDIFFERENTKEY;
2393 }
2394 else if (found_different_type_key) {
2395 // TTXProcessCommand ���� HOSTS_do_different_type_key_dialog() �������o���B
2396 id = ID_SSHDIFFERENT_TYPE_KEY;
2397 }
2398 else {
2399 // TTXProcessCommand ���� HOSTS_do_unknown_host_dialog() �������o���B
2400 id = ID_SSHUNKNOWNHOST;
2401 }
2402
2403 PostMessage(pvar->NotificationWindow, WM_COMMAND, id, 0);
2404
2405 logprintf(LOG_LEVEL_INFO, "Calling known_hosts dialog...(%s)",
2406 id == ID_SSHDIFFERENTKEY ? "SSHDIFFERENTKEY" :
2407 id == ID_SSHDIFFERENT_TYPE_KEY ? "SSHDIFFERENT_TYPE_KEY" : "SSHUNKNOWNHOST"
2408 );
2409
2410 return FALSE;
2411 }
2412
2413 /*
2414 * known_hosts�_�C�A���O�����[�U���F���ASSH�T�[�o�����l�S�V�G�[�V���������J�����B
2415 */
2416 BOOL HOSTS_resume_session_after_known_hosts(PTInstVar pvar)
2417 {
2418 enum ssh_kex_known_hosts type;
2419 int ret = FALSE;
2420
2421 type = pvar->contents_after_known_hosts.kex_type;
2422 if (type == SSH1_PUBLIC_KEY_KNOWN_HOSTS) {
2423 ret = handle_server_public_key_after_known_hosts(pvar);
2424
2425 } else if (type == SSH2_DH_KEX_REPLY_KNOWN_HOSTS) {
2426 ret = handle_SSH2_dh_kex_reply_after_known_hosts(pvar);
2427
2428 } else if (type == SSH2_DH_GEX_REPLY_KNOWN_HOSTS) {
2429 ret = handle_SSH2_dh_gex_reply_after_known_hosts(pvar);
2430
2431 } else if (type == SSH2_ECDH_KEX_REPLY_KNOWN_HOSTS) {
2432 ret = handle_SSH2_ecdh_kex_reply_after_known_hosts(pvar);
2433
2434 }
2435
2436 return (ret);
2437 }
2438
2439 /*
2440 * known_hosts�_�C�A���O��SSH�������L�����Z������
2441 */
2442 void HOSTS_cancel_session_after_known_hosts(PTInstVar pvar)
2443 {
2444 enum ssh_kex_known_hosts type;
2445
2446 type = pvar->contents_after_known_hosts.kex_type;
2447 if (type != NONE_KNOWN_HOSTS) {
2448 handle_SSH2_canel_reply_after_known_hosts(pvar);
2449 }
2450
2451 return;
2452 }
2453
2454
2455 void HOSTS_notify_disconnecting(PTInstVar pvar)
2456 {
2457 if (pvar->hosts_state.hosts_dialog != NULL) {
2458 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
2459 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
2460 EnableWindow(pvar->NotificationWindow, TRUE);
2461 }
2462 }
2463
2464 // TCP�Z�b�V�������N���[�Y�����������Aknown_hosts�_�C�A���O���������������w�����o���B
2465 // HOSTS_notify_disconnecting()�����������A�_�C�A���O���������������A
2466 // SSH�T�[�o�����m���o�������B
2467 void HOSTS_notify_closing_on_exit(PTInstVar pvar)
2468 {
2469 if (pvar->hosts_state.hosts_dialog != NULL) {
2470 logprintf(LOG_LEVEL_INFO, "%s: Notify closing message to the known_hosts dialog.", __FUNCTION__);
2471 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCLOSE, 0);
2472 }
2473 }
2474
2475 void HOSTS_end(PTInstVar pvar)
2476 {
2477 int i;
2478
2479 free(pvar->hosts_state.prefetched_hostname);
2480 key_init(&pvar->hosts_state.hostkey);
2481
2482 if (pvar->hosts_state.file_names != NULL) {
2483 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
2484 free(pvar->hosts_state.file_names[i]);
2485 }
2486 free(pvar->hosts_state.file_names);
2487 }
2488 }

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