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

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