Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/ttssh2/ttxssh/hosts.c

Parent Directory Parent Directory | Revision Log Revision Log


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