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

サーバから送られてきた鍵候補群と、known_hosts ファイルを検索し、
鍵のマッチングを行うようにした。


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     fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX);
1101     SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
1102     free(fp);
1103    
1104     // �r�W���A����fingerprint���\������
1105     fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART);
1106     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     static void add_host_key(PTInstVar pvar)
1235     {
1236     char FAR *name = NULL;
1237    
1238     if ( pvar->hosts_state.file_names != NULL)
1239     name = pvar->hosts_state.file_names[0];
1240    
1241     if (name == NULL || name[0] == 0) {
1242     UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1243     "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1244     "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1245     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1246     } else {
1247     char FAR *keydata = format_host_key(pvar);
1248     int length = strlen(keydata);
1249     int fd;
1250     int amount_written;
1251     int close_result;
1252     char buf[FILENAME_MAX];
1253    
1254     get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1255     fd = _open(buf,
1256     _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1257     _S_IREAD | _S_IWRITE);
1258     if (fd == -1) {
1259     if (errno == EACCES) {
1260     UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1261     "An error occurred while trying to write the host key.\n"
1262     "You do not have permission to write to the known-hosts file.");
1263     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1264     } else {
1265     UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1266     "An error occurred while trying to write the host key.\n"
1267     "The host key could not be written.");
1268     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1269     }
1270     return;
1271     }
1272    
1273     amount_written = _write(fd, keydata, length);
1274     free(keydata);
1275     close_result = _close(fd);
1276    
1277     if (amount_written != length || close_result == -1) {
1278     UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1279     "An error occurred while trying to write the host key.\n"
1280     "The host key could not be written.");
1281     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1282     }
1283     }
1284     }
1285    
1286     static char FAR *copy_mp_int(char FAR * num)
1287     {
1288     int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1289     char FAR *result = (char FAR *) malloc(len);
1290    
1291     if (result != NULL) {
1292     memcpy(result, num, len);
1293     }
1294    
1295     return result;
1296     }
1297    
1298     //
1299     // �����z�X�g�����e���������L�[����������
1300     // add_host_key ����������������
1301     //
1302     static void delete_different_key(PTInstVar pvar)
1303     {
1304     char FAR *name = pvar->hosts_state.file_names[0];
1305    
1306     if (name == NULL || name[0] == 0) {
1307     UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1308     "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1309     "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1310     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1311     }
1312     else {
1313     Key key; // ���������z�X�g���L�[
1314 yutakapon 5663 Key *key_freed;
1315 maya 3227 int length;
1316     char filename[MAX_PATH];
1317     char tmp[L_tmpnam];
1318     int fd;
1319     int amount_written = 0;
1320     int close_result;
1321     int data_index = 0;
1322     char buf[FILENAME_MAX];
1323    
1324     // �������������t�@�C�����J��
1325     _getcwd(filename, sizeof(filename));
1326     tmpnam_s(tmp,sizeof(tmp));
1327     strcat_s(filename, sizeof(filename), tmp);
1328     fd = _open(filename,
1329     _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1330     _S_IREAD | _S_IWRITE);
1331    
1332     if (fd == -1) {
1333     if (errno == EACCES) {
1334     UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1335     "An error occurred while trying to write the host key.\n"
1336     "You do not have permission to write to the known-hosts file.");
1337     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1338     } else {
1339     UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1340     "An error occurred while trying to write the host key.\n"
1341     "The host key could not be written.");
1342     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1343     }
1344     return;
1345     }
1346    
1347     // ���������T�[�o���L�[����������
1348 yutakapon 5545 memset(&key, 0, sizeof(key));
1349 maya 4321 switch (pvar->hosts_state.hostkey.type) {
1350     case KEY_RSA1: // SSH1
1351 maya 3227 key.type = KEY_RSA1;
1352     key.bits = pvar->hosts_state.hostkey.bits;
1353     key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1354     key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1355 maya 4321 break;
1356     case KEY_RSA: // SSH2 RSA
1357 maya 3227 key.type = KEY_RSA;
1358     key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1359 maya 4321 break;
1360     case KEY_DSA: // SSH2 DSA
1361 maya 3227 key.type = KEY_DSA;
1362     key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1363 maya 4321 break;
1364     case KEY_ECDSA256:
1365     case KEY_ECDSA384:
1366     case KEY_ECDSA521:
1367     key.type = pvar->hosts_state.hostkey.type;
1368     key.ecdsa = EC_KEY_dup(pvar->hosts_state.hostkey.ecdsa);
1369     break;
1370 yutakapon 5545 case KEY_ED25519:
1371     key.type = pvar->hosts_state.hostkey.type;
1372     key.ed25519_pk = duplicate_ED25519_PK(pvar->hosts_state.hostkey.ed25519_pk);
1373     break;
1374 maya 3227 }
1375    
1376     // �t�@�C��������������
1377     begin_read_host_files(pvar, 0);
1378     do {
1379     int host_index = 0;
1380     int matched = 0;
1381     int keybits = 0;
1382     char FAR *data;
1383     int do_write = 0;
1384     length = amount_written = 0;
1385    
1386     if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1387     break;
1388     }
1389    
1390     if (data_index == pvar->hosts_state.file_data_index) {
1391     // index ���i������ == ��������������
1392     break;
1393     }
1394    
1395     data = pvar->hosts_state.file_data + data_index;
1396     host_index = eat_spaces(data);
1397    
1398     if (data[host_index] == '#') {
1399     do_write = 1;
1400     }
1401     else {
1402     // �z�X�g������
1403     host_index--;
1404     do {
1405     int negated;
1406     int bracketed;
1407     char *end_bracket;
1408     int host_matched = 0;
1409     unsigned short keyfile_port = 22;
1410    
1411     host_index++;
1412     negated = data[host_index] == '!';
1413    
1414     if (negated) {
1415     host_index++;
1416     bracketed = data[host_index] == '[';
1417     if (bracketed) {
1418     end_bracket = strstr(data + host_index + 1, "]:");
1419     if (end_bracket != NULL) {
1420     *end_bracket = ' ';
1421     host_index++;
1422     }
1423     }
1424     host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1425     if (bracketed && end_bracket != NULL) {
1426     *end_bracket = ']';
1427     keyfile_port = atoi(end_bracket + 2);
1428     }
1429     if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1430     matched = 0;
1431     // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1432     host_index--;
1433     do {
1434     host_index++;
1435     host_index += eat_to_end_of_pattern(data + host_index);
1436     } while (data[host_index] == ',');
1437     break;
1438     }
1439     }
1440     else {
1441     bracketed = data[host_index] == '[';
1442     if (bracketed) {
1443     end_bracket = strstr(data + host_index + 1, "]:");
1444     if (end_bracket != NULL) {
1445     *end_bracket = ' ';
1446     host_index++;
1447     }
1448     }
1449     host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1450     if (bracketed && end_bracket != NULL) {
1451     *end_bracket = ']';
1452     keyfile_port = atoi(end_bracket + 2);
1453     }
1454     if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1455     matched = 1;
1456     }
1457     }
1458     host_index += eat_to_end_of_pattern(data + host_index);
1459     } while (data[host_index] == ',');
1460    
1461     // �z�X�g������������
1462 maya 4332 if (!matched) {
1463 maya 3227 do_write = 1;
1464     }
1465 maya 4332 // �z�X�g��������
1466 maya 3227 else {
1467 maya 4332 // �����`�������� or ���v�����L�[
1468     if (match_key(pvar, &key) != 0) {
1469     do_write = 1;
1470 maya 3227 }
1471 maya 4332 // �����`�������������v�������L�[���X�L�b�v������
1472 maya 3227 }
1473     }
1474    
1475     // ������������
1476     if (do_write) {
1477     length = pvar->hosts_state.file_data_index - data_index;
1478     amount_written =
1479     _write(fd, pvar->hosts_state.file_data + data_index,
1480     length);
1481    
1482     if (amount_written != length) {
1483     goto error1;
1484     }
1485     }
1486     data_index = pvar->hosts_state.file_data_index;
1487     } while (1); // ������������
1488    
1489     error1:
1490     close_result = _close(fd);
1491     if (amount_written != length || close_result == -1) {
1492     UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1493     "An error occurred while trying to write the host key.\n"
1494     "The host key could not be written.");
1495     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1496     goto error2;
1497     }
1498    
1499     // �������������t�@�C���������l�[��
1500     get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1501     _unlink(buf);
1502     rename(filename, buf);
1503    
1504     error2:
1505     _unlink(filename);
1506    
1507     finish_read_host_files(pvar, 0);
1508 yutakapon 5545
1509     // ���������������������������B
1510 yutakapon 5663 key_freed = key_new(KEY_UNSPEC);
1511     memcpy(key_freed, &key, sizeof(Key));
1512     key_free(key_freed);
1513 maya 3227 }
1514     }
1515    
1516     //
1517     // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1518     // ���[�U���m�F�������B
1519     // TODO: finger print���\�����s���B
1520     // (2006.3.25 yutaka)
1521     //
1522     static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1523     LPARAM lParam)
1524     {
1525     PTInstVar pvar;
1526     LOGFONT logfont;
1527     HFONT font;
1528     char uimsg[MAX_UIMSG];
1529    
1530     switch (msg) {
1531     case WM_INITDIALOG:
1532     pvar = (PTInstVar) lParam;
1533     pvar->hosts_state.hosts_dialog = dlg;
1534     SetWindowLong(dlg, DWL_USER, lParam);
1535    
1536     // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1537     GetWindowText(dlg, uimsg, sizeof(uimsg));
1538     UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1539     SetWindowText(dlg, pvar->ts->UIMsg);
1540     GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1541 maya 4333 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING", pvar, uimsg);
1542 maya 3227 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1543     GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1544 maya 4333 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING2", pvar, uimsg);
1545 maya 3227 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1546     GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1547     UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1548     SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1549     GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1550     UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1551     SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1552     GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1553     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1554     SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1555     GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1556     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1557     SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1558    
1559 doda 4559 switch (pvar->dns_key_check) {
1560     case DNS_VERIFY_NOTFOUND:
1561 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1562 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1563     break;
1564     case DNS_VERIFY_MATCH:
1565     case DNS_VERIFY_AUTH_MATCH:
1566 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1567 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1568     break;
1569     case DNS_VERIFY_MISMATCH:
1570     case DNS_VERIFY_AUTH_MISMATCH:
1571 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1572 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1573     break;
1574     case DNS_VERIFY_DIFFERENTTYPE:
1575     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1576 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1577 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1578     break;
1579     }
1580    
1581     switch (pvar->dns_key_check) {
1582     case DNS_VERIFY_MATCH:
1583     case DNS_VERIFY_MISMATCH:
1584     case DNS_VERIFY_DIFFERENTTYPE:
1585 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1586 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1587     break;
1588     case DNS_VERIFY_AUTH_MATCH:
1589     case DNS_VERIFY_AUTH_MISMATCH:
1590     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1591 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1592 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1593     break;
1594     }
1595    
1596 maya 3227 init_hosts_dlg(pvar, dlg);
1597    
1598     font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1599     GetObject(font, sizeof(LOGFONT), &logfont);
1600     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1601     SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1602     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1603 maya 4565 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1604     SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1605 maya 3227 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1606     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1607     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1608     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1609     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1610     }
1611     else {
1612     DlgHostsAddFont = NULL;
1613     }
1614    
1615     // add host check box���`�F�b�N���f�t�H���g������������
1616     SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1617    
1618     return TRUE; /* because we do not set the focus */
1619    
1620     case WM_COMMAND:
1621     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1622    
1623     switch (LOWORD(wParam)) {
1624     case IDC_CONTINUE:
1625 yutakapon 5562 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1626     if (!pvar->cv->Ready) {
1627     goto canceled;
1628     }
1629    
1630 maya 3227 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1631     add_host_key(pvar);
1632     }
1633    
1634     if (SSHv1(pvar)) {
1635     SSH_notify_host_OK(pvar);
1636     } else { // SSH2
1637     // SSH2���������� SSH_notify_host_OK() �������B
1638     }
1639    
1640     pvar->hosts_state.hosts_dialog = NULL;
1641    
1642     EndDialog(dlg, 1);
1643    
1644     if (DlgHostsAddFont != NULL) {
1645     DeleteObject(DlgHostsAddFont);
1646     }
1647    
1648     return TRUE;
1649    
1650     case IDCANCEL: /* kill the connection */
1651 yutakapon 5562 canceled:
1652 maya 3227 pvar->hosts_state.hosts_dialog = NULL;
1653 maya 5678 notify_closed_connection(pvar, "authentication cancelled");
1654 maya 3227 EndDialog(dlg, 0);
1655    
1656     if (DlgHostsAddFont != NULL) {
1657     DeleteObject(DlgHostsAddFont);
1658     }
1659    
1660     return TRUE;
1661    
1662     default:
1663     return FALSE;
1664     }
1665    
1666     default:
1667     return FALSE;
1668     }
1669     }
1670    
1671     //
1672     // �u�����������m�F�_�C�A���O������
1673     //
1674     static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1675     LPARAM lParam)
1676     {
1677     PTInstVar pvar;
1678     LOGFONT logfont;
1679     HFONT font;
1680     char uimsg[MAX_UIMSG];
1681    
1682     switch (msg) {
1683     case WM_INITDIALOG:
1684     pvar = (PTInstVar) lParam;
1685     pvar->hosts_state.hosts_dialog = dlg;
1686     SetWindowLong(dlg, DWL_USER, lParam);
1687    
1688     // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1689     GetWindowText(dlg, uimsg, sizeof(uimsg));
1690 maya 4330 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
1691 maya 3227 SetWindowText(dlg, pvar->ts->UIMsg);
1692     GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1693 maya 4330 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
1694 maya 3227 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1695     GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1696 maya 4330 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
1697 maya 3227 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1698     GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1699 maya 4330 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
1700 maya 3227 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1701     GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1702 maya 4330 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
1703 maya 3227 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1704     GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1705     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1706     SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1707     GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1708     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1709     SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1710    
1711 doda 4559 switch (pvar->dns_key_check) {
1712     case DNS_VERIFY_NOTFOUND:
1713 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1714 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1715     break;
1716     case DNS_VERIFY_MATCH:
1717     case DNS_VERIFY_AUTH_MATCH:
1718 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1719 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1720     break;
1721     case DNS_VERIFY_MISMATCH:
1722     case DNS_VERIFY_AUTH_MISMATCH:
1723 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1724 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1725     break;
1726     case DNS_VERIFY_DIFFERENTTYPE:
1727     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1728 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1729 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1730     break;
1731     }
1732    
1733     switch (pvar->dns_key_check) {
1734     case DNS_VERIFY_MATCH:
1735     case DNS_VERIFY_MISMATCH:
1736     case DNS_VERIFY_DIFFERENTTYPE:
1737 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1738 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1739     break;
1740     case DNS_VERIFY_AUTH_MATCH:
1741     case DNS_VERIFY_AUTH_MISMATCH:
1742     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1743 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1744 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1745     break;
1746     }
1747    
1748 maya 3227 init_hosts_dlg(pvar, dlg);
1749    
1750     font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1751     GetObject(font, sizeof(LOGFONT), &logfont);
1752     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1753     SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1754     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1755 maya 4565 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1756     SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1757 maya 3227 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1758     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1759     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1760     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1761     }
1762     else {
1763     DlgHostsReplaceFont = NULL;
1764     }
1765    
1766     // �f�t�H���g���`�F�b�N����������
1767     return TRUE; /* because we do not set the focus */
1768    
1769     case WM_COMMAND:
1770     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1771    
1772     switch (LOWORD(wParam)) {
1773     case IDC_CONTINUE:
1774 yutakapon 5562 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1775     if (!pvar->cv->Ready) {
1776     goto canceled;
1777     }
1778    
1779 maya 3227 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1780     add_host_key(pvar);
1781     delete_different_key(pvar);
1782     }
1783    
1784     if (SSHv1(pvar)) {
1785     SSH_notify_host_OK(pvar);
1786     } else { // SSH2
1787     // SSH2���������� SSH_notify_host_OK() �������B
1788     }
1789    
1790     pvar->hosts_state.hosts_dialog = NULL;
1791    
1792     EndDialog(dlg, 1);
1793    
1794     if (DlgHostsReplaceFont != NULL) {
1795     DeleteObject(DlgHostsReplaceFont);
1796     }
1797    
1798     return TRUE;
1799    
1800     case IDCANCEL: /* kill the connection */
1801 yutakapon 5562 canceled:
1802 maya 3227 pvar->hosts_state.hosts_dialog = NULL;
1803 maya 5678 notify_closed_connection(pvar, "authentication cancelled");
1804 maya 3227 EndDialog(dlg, 0);
1805    
1806     if (DlgHostsReplaceFont != NULL) {
1807     DeleteObject(DlgHostsReplaceFont);
1808     }
1809    
1810     return TRUE;
1811    
1812     default:
1813     return FALSE;
1814     }
1815    
1816     default:
1817     return FALSE;
1818     }
1819     }
1820    
1821 maya 4332 //
1822     // �����z�X�g�����`�����������������m�F�_�C�A���O������
1823     //
1824     static BOOL CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1825     LPARAM lParam)
1826     {
1827     PTInstVar pvar;
1828     LOGFONT logfont;
1829     HFONT font;
1830     char uimsg[MAX_UIMSG];
1831    
1832     switch (msg) {
1833     case WM_INITDIALOG:
1834     pvar = (PTInstVar) lParam;
1835     pvar->hosts_state.hosts_dialog = dlg;
1836     SetWindowLong(dlg, DWL_USER, lParam);
1837    
1838     // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1839     GetWindowText(dlg, uimsg, sizeof(uimsg));
1840     UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
1841     SetWindowText(dlg, pvar->ts->UIMsg);
1842     GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1843 maya 4333 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
1844 maya 4332 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1845     GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1846 maya 4333 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
1847 maya 4332 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1848     GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1849     UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
1850     SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1851     GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1852     UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
1853     SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1854     GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1855     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1856     SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1857     GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1858     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1859     SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1860    
1861 doda 4559 switch (pvar->dns_key_check) {
1862     case DNS_VERIFY_NOTFOUND:
1863 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1864 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1865     break;
1866     case DNS_VERIFY_MATCH:
1867     case DNS_VERIFY_AUTH_MATCH:
1868 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1869 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1870     break;
1871     case DNS_VERIFY_MISMATCH:
1872     case DNS_VERIFY_AUTH_MISMATCH:
1873 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1874 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1875     break;
1876     case DNS_VERIFY_DIFFERENTTYPE:
1877     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1878 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1879 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1880     break;
1881     }
1882    
1883     switch (pvar->dns_key_check) {
1884     case DNS_VERIFY_MATCH:
1885     case DNS_VERIFY_MISMATCH:
1886     case DNS_VERIFY_DIFFERENTTYPE:
1887 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1888 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1889     break;
1890     case DNS_VERIFY_AUTH_MATCH:
1891     case DNS_VERIFY_AUTH_MISMATCH:
1892     case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1893 maya 4602 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1894 doda 4559 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1895     break;
1896     }
1897    
1898 maya 4332 init_hosts_dlg(pvar, dlg);
1899    
1900     font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1901     GetObject(font, sizeof(LOGFONT), &logfont);
1902     if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1903     SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1904     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1905 maya 4565 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1906     SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1907 maya 4332 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1908     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1909     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1910     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1911     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1912     }
1913     else {
1914     DlgHostsAddFont = NULL;
1915     }
1916    
1917     // add host check box ���f�t�H���g�� off ������
1918     // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1919    
1920     return TRUE; /* because we do not set the focus */
1921    
1922     case WM_COMMAND:
1923     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1924    
1925     switch (LOWORD(wParam)) {
1926     case IDC_CONTINUE:
1927 yutakapon 5562 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1928     if (!pvar->cv->Ready) {
1929     goto canceled;
1930     }
1931    
1932 maya 4332 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1933     add_host_key(pvar);
1934     }
1935    
1936     if (SSHv1(pvar)) {
1937     SSH_notify_host_OK(pvar);
1938     } else { // SSH2
1939     // SSH2���������� SSH_notify_host_OK() �������B
1940     }
1941    
1942     pvar->hosts_state.hosts_dialog = NULL;
1943    
1944     EndDialog(dlg, 1);
1945    
1946     if (DlgHostsAddFont != NULL) {
1947     DeleteObject(DlgHostsAddFont);
1948     }
1949    
1950     return TRUE;
1951    
1952     case IDCANCEL: /* kill the connection */
1953 yutakapon 5562 canceled:
1954 maya 4332 pvar->hosts_state.hosts_dialog = NULL;
1955 maya 5678 notify_closed_connection(pvar, "authentication cancelled");
1956 maya 4332 EndDialog(dlg, 0);
1957    
1958     if (DlgHostsAddFont != NULL) {
1959     DeleteObject(DlgHostsAddFont);
1960     }
1961    
1962     return TRUE;
1963    
1964     default:
1965     return FALSE;
1966     }
1967    
1968     default:
1969     return FALSE;
1970     }
1971     }
1972    
1973 maya 3227 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1974     {
1975     if (pvar->hosts_state.hosts_dialog == NULL) {
1976     HWND cur_active = GetActiveWindow();
1977    
1978     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1979     cur_active != NULL ? cur_active : wnd,
1980     hosts_add_dlg_proc, (LPARAM) pvar);
1981     }
1982     }
1983    
1984 maya 4330 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
1985 maya 3227 {
1986     if (pvar->hosts_state.hosts_dialog == NULL) {
1987     HWND cur_active = GetActiveWindow();
1988    
1989 maya 4330 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
1990 maya 3227 cur_active != NULL ? cur_active : wnd,
1991     hosts_replace_dlg_proc, (LPARAM) pvar);
1992     }
1993     }
1994    
1995 maya 4332 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
1996     {
1997     if (pvar->hosts_state.hosts_dialog == NULL) {
1998     HWND cur_active = GetActiveWindow();
1999    
2000     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2001     cur_active != NULL ? cur_active : wnd,
2002     hosts_add2_dlg_proc, (LPARAM) pvar);
2003     }
2004     }
2005    
2006 maya 3227 //
2007     // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
2008     //
2009     // SSH2���������� (2006.3.24 yutaka)
2010     //
2011     BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
2012     {
2013 doda 4559 int found_different_key = 0, found_different_type_key = 0;
2014 maya 3227
2015 doda 4559 pvar->dns_key_check = DNS_VERIFY_NONE;
2016    
2017 maya 3227 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
2018     if (pvar->hosts_state.prefetched_hostname != NULL
2019     && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
2020 maya 4332 && match_key(pvar, key) == 1) {
2021 maya 3227
2022     if (SSHv1(pvar)) {
2023     SSH_notify_host_OK(pvar);
2024     } else {
2025     // SSH2���������� SSH_notify_host_OK() �������B
2026     }
2027     return TRUE;
2028     }
2029    
2030     // �������������������������A�������_���t�@�C��������������
2031     if (begin_read_host_files(pvar, 0)) {
2032     do {
2033     if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
2034     break;
2035     }
2036    
2037     if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
2038 maya 4332 int match = match_key(pvar, key);
2039     if (match == 1) {
2040 maya 3227 finish_read_host_files(pvar, 0);
2041     // ���������G���g�����Q�������A���v�����L�[�������������������B
2042     // SSH2���������������������������B(2006.3.29 yutaka)
2043     if (SSHv1(pvar)) {
2044     SSH_notify_host_OK(pvar);
2045     } else {
2046     // SSH2���������� SSH_notify_host_OK() �������B
2047     }
2048     return TRUE;
2049 maya 4332 }
2050     else if (match == 0) {
2051 maya 3227 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2052     found_different_key = 1;
2053     }
2054 maya 4332 else {
2055     // �L�[���`������������
2056     found_different_type_key = 1;
2057     }
2058 maya 3227 }
2059     } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2060    
2061     finish_read_host_files(pvar, 0);
2062     }
2063    
2064     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2065     pvar->hosts_state.hostkey.type = key->type;
2066 maya 4321 switch (key->type) {
2067     case KEY_RSA1: // SSH1
2068 maya 3227 pvar->hosts_state.hostkey.bits = key->bits;
2069     pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
2070     pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
2071 maya 4321 break;
2072     case KEY_RSA: // SSH2 RSA
2073 maya 3227 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
2074 maya 4321 break;
2075     case KEY_DSA: // SSH2 DSA
2076 maya 3227 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
2077 maya 4321 break;
2078     case KEY_ECDSA256: // SSH2 ECDSA
2079     case KEY_ECDSA384:
2080     case KEY_ECDSA521:
2081     pvar->hosts_state.hostkey.ecdsa = EC_KEY_dup(key->ecdsa);
2082     break;
2083 yutakapon 5545 case KEY_ED25519:
2084     pvar->hosts_state.hostkey.ed25519_pk = duplicate_ED25519_PK(key->ed25519_pk);
2085     break;
2086 maya 3227 }
2087     free(pvar->hosts_state.prefetched_hostname);
2088     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2089    
2090 yutakapon 3631 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2091     if (pvar->nocheck_known_hosts == TRUE) {
2092     return TRUE;
2093     }
2094    
2095 doda 4542 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2096 doda 4559 pvar->dns_key_check = verify_hostkey_dns(hostname, key);
2097 doda 4542 }
2098    
2099 maya 3227 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
2100     // �������K�v�����������A�����R�[�������X�����B
2101     // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
2102     // (2007.10.1 yutaka)
2103     if (found_different_key) {
2104 maya 4330 HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar);
2105 maya 4332 }
2106     else if (found_different_type_key) {
2107     HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar);
2108     }
2109     else {
2110 maya 3227 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
2111     }
2112    
2113     return TRUE;
2114     }
2115    
2116     void HOSTS_notify_disconnecting(PTInstVar pvar)
2117     {
2118     if (pvar->hosts_state.hosts_dialog != NULL) {
2119 doda 4531 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
2120 maya 3227 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
2121     EnableWindow(pvar->NotificationWindow, TRUE);
2122     }
2123     }
2124    
2125     void HOSTS_end(PTInstVar pvar)
2126     {
2127     int i;
2128    
2129     free(pvar->hosts_state.prefetched_hostname);
2130     init_hostkey(&pvar->hosts_state.hostkey);
2131    
2132     if (pvar->hosts_state.file_names != NULL) {
2133     for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
2134     free(pvar->hosts_state.file_names[i]);
2135     }
2136     free(pvar->hosts_state.file_names);
2137     }
2138     }

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