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

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

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

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