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 5846 - (show annotations) (download) (as text)
Sun May 3 16:46:29 2015 UTC (8 years, 11 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 60976 byte(s)
チケット #35047 SSH サーバホスト公開鍵の自動更新

known_hosts ファイルを検索する関数(host key rotation用)を追加した。

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

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