Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9210 - (hide 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 maya 3227 /*
2 doda 6841 * Copyright (c) 1998-2001, Robert O'Callahan
3 nmaya 9049 * (C) 2004- TeraTerm Project
4 doda 6841 * 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 maya 3227
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 maya 4304 #include "key.h"
40 maya 3227 #include "hosts.h"
41 doda 4569 #include "dns.h"
42 zmatsuo 7560 #include "dlglib.h"
43 zmatsuo 7714 #include "compat_win.h"
44 maya 3227
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 doda 4531 #include <memory.h>
56 maya 3227
57 doda 4531
58 zmatsuo 7560 #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 maya 3227
65     // BASE64�\���������i��������'='�����������������j
66     static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
67    
68    
69 yutakapon 8093 BOOL HOSTS_resume_session_after_known_hosts(PTInstVar pvar);
70     void HOSTS_cancel_session_after_known_hosts(PTInstVar pvar);
71    
72    
73 doda 6801 static char **parse_multi_path(char *buf)
74 maya 3227 {
75     int i;
76     int ch;
77     int num_paths = 1;
78 doda 6801 char ** result;
79 maya 3227 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 doda 6801 (char **) malloc(sizeof(char *) * (num_paths + 1));
89 maya 3227
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 maya 6147 key_init(&pvar->hosts_state.hostkey);
113 maya 3227 pvar->hosts_state.hosts_dialog = NULL;
114     pvar->hosts_state.file_names = NULL;
115 yutakapon 8093
116     /*
117     * �O�����I�v�V�����w��(/nosecuritywarning)���c���������������������������B
118     */
119     pvar->nocheck_known_hosts = FALSE;
120 maya 3227 }
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 doda 6801 static int begin_read_file(PTInstVar pvar, char *name,
132 maya 3227 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 doda 6801 static int eat_base64(char *data)
216 maya 3227 {
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 doda 6801 static int eat_spaces(char *data)
234 maya 3227 {
235     int index = 0;
236     int ch;
237    
238     while ((ch = data[index]) == ' ' || ch == '\t') {
239     index++;
240     }
241     return index;
242     }
243    
244 doda 6801 static int eat_digits(char *data)
245 maya 3227 {
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 doda 6801 static int eat_to_end_of_line(char *data)
256 maya 3227 {
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 doda 6801 static int eat_to_end_of_pattern(char *data)
272 maya 3227 {
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 doda 6621 static Key *parse_base64data(char *data)
285 maya 3227 {
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 doda 6621 n = b64decode(blob, len, data);
303 maya 3227 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 doda 6801 static char *parse_bignum(char *data)
321 maya 3227 {
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 doda 6801 char *result;
328 maya 3227 int ch;
329     int leftover_digits = 1;
330    
331 yutakapon 8316 // BN_CTX_init������ OpenSSL 1.1.0 �������������B
332     // OpenSSL 1.0.2�����_�������� deprecated �����������B
333 maya 3227 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 doda 6801 result = (char *) malloc(2 + BN_num_bytes(num));
356 maya 3227 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 doda 6801 static int check_host_key(PTInstVar pvar, char *hostname,
371     unsigned short tcpport, char *data,
372 maya 6152 Key *key)
373 maya 3227 {
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 maya 6152 key->type = KEY_RSA1;
462 maya 3227
463 maya 6152 key->bits = rsa1_key_bits;
464 maya 3227 index += eat_digits(data + index);
465     index += eat_spaces(data + index);
466    
467 maya 6152 key->exp = parse_bignum(data + index);
468 maya 3227 index += eat_digits(data + index);
469     index += eat_spaces(data + index);
470    
471 maya 6152 key->mod = parse_bignum(data + index);
472 maya 3227 } else {
473     char *cp, *p;
474 maya 6152 Key *key2;
475     ssh_keytype key_type;
476 maya 3227
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 nmaya 9210 key_type = get_hostkey_type_from_name(cp);
489 maya 3227 *p = ' ';
490    
491     index += eat_spaces(data + index); // update index
492    
493 doda 6621 // base64 decode
494     key2 = parse_base64data(data + index);
495 maya 6152 if (key2 == NULL) {
496 maya 3227 return index + eat_to_end_of_line(data + index);
497     }
498    
499     // setup
500 maya 6152 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 maya 3227
506     index += eat_base64(data + index);
507     index += eat_spaces(data + index);
508    
509     // Key�\�������g���������� (2008.3.2 yutaka)
510 maya 6152 free(key2);
511 maya 3227 }
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 maya 6152 // return_always
520     // 0: �������������T��
521     // 1: 1�s�����T��������
522 maya 3227 //
523     static int read_host_key(PTInstVar pvar,
524 doda 6801 char *hostname, unsigned short tcpport,
525 maya 6152 int suppress_errors, int return_always,
526     Key *key)
527 maya 3227 {
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 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
540 maya 3227 }
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 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
551 maya 3227 }
552     return 0;
553     }
554    
555     // hostkey type is KEY_UNSPEC.
556 maya 6152 key_init(key);
557 maya 3227
558     do {
559     if (pvar->hosts_state.file_data == NULL
560     || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
561 doda 6801 char *filename;
562 maya 3227 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 maya 6152 pvar->hosts_state.file_data_index,
591     key);
592 maya 3227
593     if (!return_always) {
594     // �L�����L�[��������������
595 maya 6152 while_flg = (key->type == KEY_UNSPEC);
596 maya 3227 }
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 doda 6801 void HOSTS_prefetch_host_key(PTInstVar pvar, char *hostname, unsigned short tcpport)
614 maya 3227 {
615 maya 6152 Key key; // known_hosts���o�^������������
616    
617 maya 3227 if (!begin_read_host_files(pvar, 1)) {
618     return;
619     }
620    
621 maya 6152 memset(&key, 0, sizeof(key));
622     if (!read_host_key(pvar, hostname, tcpport, 1, 0, &key)) {
623 maya 3227 return;
624     }
625    
626 maya 6152 key_copy(&pvar->hosts_state.hostkey, &key);
627     key_init(&key);
628    
629 maya 3227 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 yutakapon 5846
636     // known_hosts�t�@�C�������Y�������L�[���������������B
637     //
638     // return:
639     // *keyptr != NULL ��������
640     //
641 doda 6801 static int parse_hostkey_file(PTInstVar pvar, char *hostname,
642     unsigned short tcpport, char *data, Key **keyptr)
643 yutakapon 5846 {
644     int index = eat_spaces(data);
645     int matched = 0;
646     int keybits = 0;
647     ssh_keytype ktype;
648 yutakapon 5847 Key *key;
649 yutakapon 5846
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 yutakapon 5847
737     key = key_new(KEY_RSA1);
738     key->bits = rsa1_key_bits;
739    
740 yutakapon 5846 index += eat_digits(data + index);
741     index += eat_spaces(data + index);
742 yutakapon 5847 key->exp = parse_bignum(data + index);
743 yutakapon 5846
744     index += eat_digits(data + index);
745     index += eat_spaces(data + index);
746 yutakapon 5847 key->mod = parse_bignum(data + index);
747 yutakapon 5846
748 yutakapon 5847 // setup
749     *keyptr = key;
750    
751 yutakapon 5846 }
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 nmaya 9210 ktype = get_hostkey_type_from_name(cp);
767 yutakapon 5846 *p = ' ';
768    
769     index += eat_spaces(data + index); // update index
770    
771 doda 6621 // base64 decode
772     key = parse_base64data(data + index);
773 yutakapon 5846 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 doda 6801 char *filename;
799 yutakapon 5846 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 yutakapon 5847 // �Y�����������������������A�R�[���o�b�N�����������o���B
836 yutakapon 5846 if (key != NULL) {
837 yutakapon 5847 if (callback(key, ctx) == 0)
838     key_free(key);
839 yutakapon 5846 }
840     }
841    
842     success = 1;
843    
844     error:
845     finish_read_host_files(pvar, 1);
846    
847     return (success);
848     }
849    
850    
851 doda 6801 static BOOL equal_mp_ints(unsigned char *num1,
852     unsigned char *num2)
853 maya 3227 {
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 yutakapon 5843
868     // ���J�������r���s���B
869     //
870     // return
871 maya 4332 // -1 ... �����^������
872     // 0 ... ����������
873     // 1 ... ������
874 yutakapon 5843 int HOSTS_compare_public_key(Key *src, Key *key)
875 maya 3227 {
876     int bits;
877 doda 6801 unsigned char *exp;
878     unsigned char *mod;
879 maya 4321 const EC_GROUP *group;
880     const EC_POINT *pa, *pb;
881 yutakapon 5545 Key *a, *b;
882 yutakapon 8316 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 maya 3227
887 yutakapon 5843 if (src->type != key->type) {
888 maya 4332 return -1;
889     }
890    
891 maya 4321 switch (key->type) {
892     case KEY_RSA1: // SSH1 host public key
893 maya 3227 bits = key->bits;
894     exp = key->exp;
895     mod = key->mod;
896    
897     /* just check for equal exponent and modulus */
898 yutakapon 5843 return equal_mp_ints(exp, src->exp)
899     && equal_mp_ints(mod, src->mod);
900 maya 3227 /*
901     return equal_mp_ints(exp, pvar->hosts_state.key_exp)
902 yutakapon 5843 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
903     */
904 maya 3227
905 maya 4321 case KEY_RSA: // SSH2 RSA host public key
906 yutakapon 8316 RSA_get0_key(key->rsa, &n, &e, NULL);
907     RSA_get0_key(src->rsa, &sn, &se, NULL);
908 yutakapon 5843 return key->rsa != NULL && src->rsa != NULL &&
909 yutakapon 8316 BN_cmp(e, se) == 0 &&
910     BN_cmp(n, sn) == 0;
911 maya 3227
912 maya 4321 case KEY_DSA: // SSH2 DSA host public key
913 yutakapon 8316 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 yutakapon 5843 return key->dsa != NULL && src->dsa &&
918 yutakapon 8316 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 maya 3227
923 maya 4321 case KEY_ECDSA256:
924     case KEY_ECDSA384:
925     case KEY_ECDSA521:
926 yutakapon 5843 if (key->ecdsa == NULL || src->ecdsa == NULL) {
927 maya 4321 return FALSE;
928     }
929     group = EC_KEY_get0_group(key->ecdsa);
930     pa = EC_KEY_get0_public_key(key->ecdsa),
931 yutakapon 5843 pb = EC_KEY_get0_public_key(src->ecdsa);
932 maya 4321 return EC_POINT_cmp(group, pa, pb, NULL) == 0;
933    
934 yutakapon 5545 case KEY_ED25519:
935     a = key;
936 yutakapon 5843 b = src;
937 yutakapon 5545 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
938 yutakapon 5843 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
939 yutakapon 5545
940 maya 4321 default:
941 maya 4307 return FALSE;
942     }
943 yutakapon 5843 }
944 maya 3227
945 maya 6152 #if 0
946     // pvar->hosts_state.hostkey ���n���������J����������������������
947 yutakapon 5843 // -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 maya 3227 }
954 maya 6152 #endif
955 maya 3227
956 maya 6132 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 maya 6158 if (fp != NULL) {
965     SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
966     free(fp);
967     }
968 maya 6132 break;
969     case SSH_DIGEST_SHA256:
970 maya 6158 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 maya 6132 break;
977     }
978    
979     // �r�W���A����fingerprint���\������
980     fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART, dgst_alg);
981 maya 6158 if (fp != NULL) {
982     SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
983     free(fp);
984     }
985 maya 6132 }
986    
987 maya 3227 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 zmatsuo 7714 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 maya 3227
1014 maya 6145 CheckDlgButton(dlg, IDC_FP_HASH_ALG_SHA256, TRUE);
1015     hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
1016 maya 3227 }
1017    
1018 doda 6801 static int print_mp_int(char *buf, unsigned char *mp)
1019 maya 3227 {
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 doda 6801 static char *format_host_key(PTInstVar pvar)
1046 maya 3227 {
1047     int host_len = strlen(pvar->hosts_state.prefetched_hostname);
1048     char *result = NULL;
1049     int index;
1050 maya 4378 ssh_keytype type = pvar->hosts_state.hostkey.type;
1051 maya 3227
1052 maya 4321 switch (type) {
1053     case KEY_RSA1:
1054     {
1055 maya 3227 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 doda 6801 result = (char *) malloc(result_len);
1059 maya 3227
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 yutakapon 7889 // ��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 maya 3227 " %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 maya 4321 break;
1087     }
1088    
1089     case KEY_RSA:
1090     case KEY_DSA:
1091     case KEY_ECDSA256:
1092     case KEY_ECDSA384:
1093     case KEY_ECDSA521:
1094 yutakapon 5545 case KEY_ED25519:
1095 maya 4321 {
1096 maya 3227 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 nmaya 9210 get_ssh2_hostkey_type_name_from_key(key),
1121 maya 3227 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 nmaya 9210 get_ssh2_hostkey_type_name_from_key(key),
1127 maya 3227 uu);
1128     }
1129     }
1130     error:
1131     if (blob != NULL)
1132     free(blob);
1133     if (uu != NULL)
1134     free(uu);
1135    
1136 maya 4321 break;
1137     }
1138    
1139     default:
1140 maya 3227 return NULL;
1141    
1142     }
1143    
1144     return result;
1145     }
1146    
1147 doda 6801 static char *format_specified_host_key(Key *key, char *hostname, unsigned short tcpport)
1148 yutakapon 5849 {
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 doda 6801 result = (char *) malloc(result_len);
1161 yutakapon 5849
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 nmaya 9210 get_ssh2_hostkey_type_name_from_key(key),
1217 yutakapon 5849 uu);
1218     }
1219     else {
1220     _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1221     hostname,
1222     tcpport,
1223 nmaya 9210 get_ssh2_hostkey_type_name_from_key(key),
1224 yutakapon 5849 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 maya 3227 static void add_host_key(PTInstVar pvar)
1245     {
1246 doda 6801 char *name = NULL;
1247 maya 3227
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 doda 6801 char *keydata = format_host_key(pvar);
1258 maya 3227 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 yutakapon 5849 // �w�������L�[�� known_hosts �����������B
1297     void HOSTS_add_host_key(PTInstVar pvar, Key *key)
1298     {
1299 doda 6801 char *name = NULL;
1300 yutakapon 5849 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 doda 6801 char *keydata = format_specified_host_key(key, hostname, tcpport);
1317 yutakapon 5849 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 maya 3227 //
1357     // �����z�X�g�����e���������L�[����������
1358     // add_host_key ����������������
1359     //
1360     static void delete_different_key(PTInstVar pvar)
1361     {
1362 doda 6801 char *name = pvar->hosts_state.file_names[0];
1363 maya 3227
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 maya 6152 Key key; // known_hosts���o�^������������
1372 maya 3227 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 youlab 9179 char *newfiledata = NULL;
1379     int ret;
1380     struct _stat fileStat;
1381     long newFilePos = 0, totalSize;
1382 maya 3227
1383 youlab 9179 // 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 maya 3227 }
1390 youlab 9179 // �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 maya 3227
1398 youlab 9179
1399 maya 6152 // �t�@�C��������������
1400 maya 6147 memset(&key, 0, sizeof(key));
1401 maya 3227 begin_read_host_files(pvar, 0);
1402     do {
1403     int host_index = 0;
1404     int matched = 0;
1405     int keybits = 0;
1406 doda 6801 char *data;
1407 maya 3227 int do_write = 0;
1408     length = amount_written = 0;
1409    
1410 maya 6152 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1411 maya 3227 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 maya 4332 if (!matched) {
1487 maya 3227 do_write = 1;
1488     }
1489 maya 4332 // �z�X�g��������
1490 maya 3227 else {
1491 maya 4332 // �����`�������� or ���v�����L�[
1492 maya 6152 if (HOSTS_compare_public_key(&pvar->hosts_state.hostkey, &key) != 0) {
1493 maya 4332 do_write = 1;
1494 maya 3227 }
1495 maya 4332 // �����`�������������v�������L�[���X�L�b�v������
1496 maya 3227 }
1497     }
1498    
1499     // ������������
1500     if (do_write) {
1501     length = pvar->hosts_state.file_data_index - data_index;
1502    
1503 youlab 9179 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 maya 3227 }
1517     data_index = pvar->hosts_state.file_data_index;
1518     } while (1); // ������������
1519    
1520 youlab 9179 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 maya 3227 close_result = _close(fd);
1548 youlab 9179 if (amount_written != newFilePos || close_result == -1) {
1549 maya 3227 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1550 youlab 9179 "An error occurred while trying to write the host key.\n"
1551     "The host key could not be written.");
1552 maya 3227 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1553 youlab 9179 goto error;
1554     }
1555    
1556     error:
1557     if (newfiledata) {
1558     free(newfiledata);
1559 maya 3227 }
1560    
1561     }
1562     }
1563    
1564 yutakapon 5849
1565     void HOSTS_delete_all_hostkeys(PTInstVar pvar)
1566     {
1567 doda 6801 char *name = pvar->hosts_state.file_names[0];
1568 yutakapon 5849 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 maya 6152 Key key; // known_hosts���o�^������������
1582 yutakapon 5849 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 youlab 9178 char *newfiledata = NULL;
1589     int ret;
1590     struct _stat fileStat;
1591     long newFilePos = 0, totalSize;
1592 yutakapon 5849
1593 youlab 9178 // 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 yutakapon 5849 }
1600 youlab 9178 // �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 yutakapon 5849
1608 maya 6152 // �t�@�C��������������
1609 maya 6147 memset(&key, 0, sizeof(key));
1610 yutakapon 5849 begin_read_host_files(pvar, 0);
1611     do {
1612     int host_index = 0;
1613     int matched = 0;
1614     int keybits = 0;
1615 doda 6801 char *data;
1616 yutakapon 5849 int do_write = 0;
1617     length = amount_written = 0;
1618    
1619 maya 6152 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1620 yutakapon 5849 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 youlab 9178
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 yutakapon 5849 length);
1720 youlab 9178 newFilePos += length;
1721 yutakapon 5849
1722     }
1723     data_index = pvar->hosts_state.file_data_index;
1724     } while (1); // ������������
1725    
1726 youlab 9178 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 yutakapon 5849 close_result = _close(fd);
1754 youlab 9178 if (amount_written != newFilePos || close_result == -1) {
1755 yutakapon 5849 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 youlab 9178 goto error;
1760     }
1761    
1762     error:
1763     if (newfiledata) {
1764     free(newfiledata);
1765 yutakapon 5849 }
1766    
1767     }
1768     }
1769    
1770    
1771 maya 3227 //
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 zmatsuo 7896 static INT_PTR CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1778     LPARAM lParam)
1779 maya 3227 {
1780 zmatsuo 8240 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 maya 3227 PTInstVar pvar;
1791    
1792     switch (msg) {
1793     case WM_INITDIALOG:
1794     pvar = (PTInstVar) lParam;
1795     pvar->hosts_state.hosts_dialog = dlg;
1796 zmatsuo 7896 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1797 maya 3227
1798     // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1799 zmatsuo 8240 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
1800 maya 3227
1801 doda 4559 switch (pvar->dns_key_check) {
1802     case DNS_VERIFY_NOTFOUND:
1803 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1804 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1805     break;
1806     case DNS_VERIFY_MATCH:
1807     case DNS_VERIFY_AUTH_MATCH:
1808 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1809 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1810     break;
1811     case DNS_VERIFY_MISMATCH:
1812     case DNS_VERIFY_AUTH_MISMATCH:
1813 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1814 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1815     break;
1816     case DNS_VERIFY_DIFFERENTTYPE:
1817     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1818 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1819 doda 4559 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 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1828 doda 4559 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 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1834 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1835     break;
1836     }
1837    
1838 maya 3227 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 zmatsuo 7592 CenterWindow(dlg, GetParent(dlg));
1843    
1844 maya 3227 return TRUE; /* because we do not set the focus */
1845    
1846     case WM_COMMAND:
1847 zmatsuo 7896 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
1848 maya 3227
1849     switch (LOWORD(wParam)) {
1850     case IDC_CONTINUE:
1851 yutakapon 5562 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1852     if (!pvar->cv->Ready) {
1853     goto canceled;
1854     }
1855    
1856 maya 3227 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1857     add_host_key(pvar);
1858     }
1859    
1860 yutakapon 8093 /*
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 maya 3227
1866     pvar->hosts_state.hosts_dialog = NULL;
1867    
1868     EndDialog(dlg, 1);
1869     return TRUE;
1870    
1871     case IDCANCEL: /* kill the connection */
1872 yutakapon 5562 canceled:
1873 yutakapon 8093 /*
1874     * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
1875     */
1876     HOSTS_cancel_session_after_known_hosts(pvar);
1877    
1878 maya 3227 pvar->hosts_state.hosts_dialog = NULL;
1879 maya 5678 notify_closed_connection(pvar, "authentication cancelled");
1880 maya 3227 EndDialog(dlg, 0);
1881     return TRUE;
1882    
1883 yutakapon 8093 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 maya 6132 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 maya 3227 default:
1903     return FALSE;
1904     }
1905    
1906 zmatsuo 7714 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 maya 3227 default:
1927     return FALSE;
1928     }
1929     }
1930    
1931     //
1932     // �u�����������m�F�_�C�A���O������
1933     //
1934 zmatsuo 7896 static INT_PTR CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1935     LPARAM lParam)
1936 maya 3227 {
1937 zmatsuo 8240 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 maya 3227 PTInstVar pvar;
1948    
1949     switch (msg) {
1950     case WM_INITDIALOG:
1951     pvar = (PTInstVar) lParam;
1952     pvar->hosts_state.hosts_dialog = dlg;
1953 zmatsuo 7896 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1954 maya 3227
1955     // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1956 zmatsuo 8240 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
1957 maya 3227
1958 doda 4559 switch (pvar->dns_key_check) {
1959     case DNS_VERIFY_NOTFOUND:
1960 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1961 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1962     break;
1963     case DNS_VERIFY_MATCH:
1964     case DNS_VERIFY_AUTH_MATCH:
1965 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1966 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1967     break;
1968     case DNS_VERIFY_MISMATCH:
1969     case DNS_VERIFY_AUTH_MISMATCH:
1970 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1971 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1972     break;
1973     case DNS_VERIFY_DIFFERENTTYPE:
1974     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1975 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1976 doda 4559 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 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1985 doda 4559 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 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1991 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1992     break;
1993     }
1994    
1995 maya 3227 init_hosts_dlg(pvar, dlg);
1996 zmatsuo 7592 CenterWindow(dlg, GetParent(dlg));
1997 maya 3227 // �f�t�H���g���`�F�b�N����������
1998     return TRUE; /* because we do not set the focus */
1999    
2000     case WM_COMMAND:
2001 zmatsuo 7896 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2002 maya 3227
2003     switch (LOWORD(wParam)) {
2004     case IDC_CONTINUE:
2005 yutakapon 5562 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2006     if (!pvar->cv->Ready) {
2007     goto canceled;
2008     }
2009    
2010 maya 3227 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2011     add_host_key(pvar);
2012     delete_different_key(pvar);
2013     }
2014    
2015 yutakapon 8093 /*
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 maya 3227
2021     pvar->hosts_state.hosts_dialog = NULL;
2022    
2023     EndDialog(dlg, 1);
2024     return TRUE;
2025    
2026     case IDCANCEL: /* kill the connection */
2027 yutakapon 5562 canceled:
2028 yutakapon 8093 /*
2029     * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
2030     */
2031     HOSTS_cancel_session_after_known_hosts(pvar);
2032    
2033 maya 3227 pvar->hosts_state.hosts_dialog = NULL;
2034 maya 5678 notify_closed_connection(pvar, "authentication cancelled");
2035 maya 3227 EndDialog(dlg, 0);
2036     return TRUE;
2037    
2038 yutakapon 8093 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 maya 6132 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 maya 3227 default:
2058     return FALSE;
2059     }
2060    
2061 zmatsuo 7714 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 maya 3227 default:
2082     return FALSE;
2083     }
2084     }
2085    
2086 maya 4332 //
2087     // �����z�X�g�����`�����������������m�F�_�C�A���O������
2088     //
2089 zmatsuo 7896 static INT_PTR CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2090     LPARAM lParam)
2091 maya 4332 {
2092 zmatsuo 8240 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 maya 4332 PTInstVar pvar;
2103    
2104     switch (msg) {
2105     case WM_INITDIALOG:
2106     pvar = (PTInstVar) lParam;
2107     pvar->hosts_state.hosts_dialog = dlg;
2108 zmatsuo 7896 SetWindowLongPtr(dlg, DWLP_USER, lParam);
2109 maya 4332
2110     // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2111 zmatsuo 8240 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
2112 maya 4332
2113 doda 4559 switch (pvar->dns_key_check) {
2114     case DNS_VERIFY_NOTFOUND:
2115 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2116 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2117     break;
2118     case DNS_VERIFY_MATCH:
2119     case DNS_VERIFY_AUTH_MATCH:
2120 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2121 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2122     break;
2123     case DNS_VERIFY_MISMATCH:
2124     case DNS_VERIFY_AUTH_MISMATCH:
2125 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2126 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2127     break;
2128     case DNS_VERIFY_DIFFERENTTYPE:
2129     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2130 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2131 doda 4559 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 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2140 doda 4559 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 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2146 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2147     break;
2148     }
2149    
2150 maya 4332 init_hosts_dlg(pvar, dlg);
2151 zmatsuo 7592 CenterWindow(dlg, GetParent(dlg));
2152 maya 4332 // 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 zmatsuo 7896 pvar = (PTInstVar) GetWindowLongPtr(dlg, DWLP_USER);
2159 maya 4332
2160     switch (LOWORD(wParam)) {
2161     case IDC_CONTINUE:
2162 yutakapon 5562 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2163     if (!pvar->cv->Ready) {
2164     goto canceled;
2165     }
2166    
2167 maya 4332 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2168     add_host_key(pvar);
2169     }
2170    
2171 yutakapon 8093 /*
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 maya 4332
2177     pvar->hosts_state.hosts_dialog = NULL;
2178    
2179     EndDialog(dlg, 1);
2180     return TRUE;
2181    
2182     case IDCANCEL: /* kill the connection */
2183 yutakapon 5562 canceled:
2184 yutakapon 8093 /*
2185     * known_hosts���L�����Z�����������A���J�p�����\�[�X���j�����������B
2186     */
2187     HOSTS_cancel_session_after_known_hosts(pvar);
2188    
2189 maya 4332 pvar->hosts_state.hosts_dialog = NULL;
2190 maya 5678 notify_closed_connection(pvar, "authentication cancelled");
2191 maya 4332 EndDialog(dlg, 0);
2192     return TRUE;
2193    
2194 yutakapon 8093 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 maya 6132 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 maya 4332 default:
2214     return FALSE;
2215     }
2216    
2217 zmatsuo 7714 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 maya 4332 default:
2238     return FALSE;
2239     }
2240     }
2241    
2242 maya 3227 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
2243     {
2244     if (pvar->hosts_state.hosts_dialog == NULL) {
2245 yutakapon 8093 /* 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 maya 3227
2255     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
2256     cur_active != NULL ? cur_active : wnd,
2257     hosts_add_dlg_proc, (LPARAM) pvar);
2258     }
2259     }
2260    
2261 maya 4330 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
2262 maya 3227 {
2263     if (pvar->hosts_state.hosts_dialog == NULL) {
2264 yutakapon 8093 /* 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 maya 3227
2274 maya 4330 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
2275 maya 3227 cur_active != NULL ? cur_active : wnd,
2276     hosts_replace_dlg_proc, (LPARAM) pvar);
2277     }
2278     }
2279    
2280 maya 4332 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
2281     {
2282     if (pvar->hosts_state.hosts_dialog == NULL) {
2283 yutakapon 8093 /* 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 maya 4332
2293     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2294     cur_active != NULL ? cur_active : wnd,
2295     hosts_add2_dlg_proc, (LPARAM) pvar);
2296     }
2297     }
2298    
2299 yutakapon 8093 /*
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 doda 6801 BOOL HOSTS_check_host_key(PTInstVar pvar, char *hostname, unsigned short tcpport, Key *key)
2313 maya 3227 {
2314 doda 4559 int found_different_key = 0, found_different_type_key = 0;
2315 maya 6152 Key key2; // known_hosts���o�^������������
2316 yutakapon 8093 DWORD id;
2317 maya 3227
2318 doda 4559 pvar->dns_key_check = DNS_VERIFY_NONE;
2319    
2320 maya 3227 // ������ 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 maya 6152 && HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key) == 1) {
2324 maya 3227
2325 yutakapon 8093 // ���������������B
2326     return TRUE;
2327 maya 3227 }
2328    
2329     // �������������������������A�������_���t�@�C��������������
2330 maya 6152 memset(&key2, 0, sizeof(key2));
2331 maya 3227 if (begin_read_host_files(pvar, 0)) {
2332     do {
2333 maya 6152 if (!read_host_key(pvar, hostname, tcpport, 0, 0, &key2)) {
2334 maya 3227 break;
2335     }
2336    
2337 maya 6152 if (key2.type != KEY_UNSPEC) {
2338     int match = HOSTS_compare_public_key(&key2, key);
2339 maya 4332 if (match == 1) {
2340 maya 3227 finish_read_host_files(pvar, 0);
2341     // ���������G���g�����Q�������A���v�����L�[�������������������B
2342 maya 6998 // About TTSSH �_�C�A���O�����\�����������A�������������������B
2343     key_copy(&pvar->hosts_state.hostkey, key);
2344    
2345 maya 3227 return TRUE;
2346 maya 4332 }
2347     else if (match == 0) {
2348 maya 3227 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2349     found_different_key = 1;
2350     }
2351 maya 4332 else {
2352     // �L�[���`������������
2353     found_different_type_key = 1;
2354     }
2355 maya 3227 }
2356 maya 6152 } while (key2.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2357 maya 3227
2358 maya 6152 key_init(&key2);
2359 maya 3227 finish_read_host_files(pvar, 0);
2360     }
2361    
2362     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2363 maya 6147 key_copy(&pvar->hosts_state.hostkey, key);
2364 maya 6145
2365 maya 3227 free(pvar->hosts_state.prefetched_hostname);
2366     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2367    
2368 yutakapon 3631 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2369     if (pvar->nocheck_known_hosts == TRUE) {
2370 yutakapon 8093 // ���������������B
2371 yutakapon 3631 return TRUE;
2372     }
2373    
2374 doda 4542 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2375 maya 6063 pvar->dns_key_check = verify_hostkey_dns(pvar, hostname, key);
2376 doda 4542 }
2377    
2378 maya 3227 // 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