Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5849 - (show annotations) (download) (as text)
Tue May 5 18:08:23 2015 UTC (8 years, 11 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 71383 byte(s)
チケット #35047 SSH サーバホスト公開鍵の自動更新

・UpdateHostkeys エントリに"2"(ASK)を追加した。
・known_hosts ファイルの更新処理を追加した。

1 /*
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 #include "key.h"
39 #include "hosts.h"
40 #include "dns.h"
41
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 #include <memory.h>
53
54
55 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 if (key->ecdsa != NULL) {
88 EC_KEY_free(key->ecdsa);
89 key->ecdsa = NULL;
90 }
91 }
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 int uudecode(unsigned char *src, int srclen, unsigned char *target, int targsize)
304 {
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 pvar->hosts_state.hostkey.ecdsa = key->ecdsa;
647 pvar->hosts_state.hostkey.ed25519_pk = key->ed25519_pk;
648
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 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
679 }
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 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
690 }
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
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 Key *key;
781
782 *keyptr = NULL;
783
784 if (data[index] == '#') {
785 return index + eat_to_end_of_line(data + index);
786 }
787
788 /* if we find an empty line, then it won't have any patterns matching the hostname
789 and so we skip it */
790 index--;
791 do {
792 int negated;
793 int bracketed;
794 char *end_bracket;
795 int host_matched = 0;
796 unsigned short keyfile_port = 22;
797
798 index++;
799 negated = data[index] == '!';
800
801 if (negated) {
802 index++;
803 bracketed = data[index] == '[';
804 if (bracketed) {
805 end_bracket = strstr(data + index + 1, "]:");
806 if (end_bracket != NULL) {
807 *end_bracket = ' ';
808 index++;
809 }
810 }
811 host_matched = match_pattern(data + index, hostname);
812 if (bracketed && end_bracket != NULL) {
813 *end_bracket = ']';
814 keyfile_port = atoi(end_bracket + 2);
815 }
816 if (host_matched && keyfile_port == tcpport) {
817 return index + eat_to_end_of_line(data + index);
818 }
819 }
820 else {
821 bracketed = data[index] == '[';
822 if (bracketed) {
823 end_bracket = strstr(data + index + 1, "]:");
824 if (end_bracket != NULL) {
825 *end_bracket = ' ';
826 index++;
827 }
828 }
829 host_matched = match_pattern(data + index, hostname);
830 if (bracketed && end_bracket != NULL) {
831 *end_bracket = ']';
832 keyfile_port = atoi(end_bracket + 2);
833 }
834 if (host_matched && keyfile_port == tcpport) {
835 matched = 1;
836 }
837 }
838
839 index += eat_to_end_of_pattern(data + index);
840 } while (data[index] == ',');
841
842 if (!matched) {
843 return index + eat_to_end_of_line(data + index);
844 }
845 else {
846 // ���������������t�H�[�}�b�g��������
847 // �����A���������v�����G���g�����������������������B
848 /*
849 [SSH1]
850 192.168.1.2 1024 35 13032....
851
852 [SSH2]
853 192.168.1.2 ssh-rsa AAAAB3NzaC1....
854 192.168.1.2 ssh-dss AAAAB3NzaC1....
855 192.168.1.2 rsa AAAAB3NzaC1....
856 192.168.1.2 dsa AAAAB3NzaC1....
857 192.168.1.2 rsa1 AAAAB3NzaC1....
858 */
859 int rsa1_key_bits;
860
861 index += eat_spaces(data + index);
862
863 rsa1_key_bits = atoi(data + index);
864 if (rsa1_key_bits > 0) { // RSA1������
865 if (!SSHv1(pvar)) { // SSH2��������������������
866 return index + eat_to_end_of_line(data + index);
867 }
868
869 key = key_new(KEY_RSA1);
870 key->bits = rsa1_key_bits;
871
872 index += eat_digits(data + index);
873 index += eat_spaces(data + index);
874 key->exp = parse_bignum(data + index);
875
876 index += eat_digits(data + index);
877 index += eat_spaces(data + index);
878 key->mod = parse_bignum(data + index);
879
880 // setup
881 *keyptr = key;
882
883 }
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 // �Y�����������������������A�R�[���o�b�N�����������o���B
968 if (key != NULL) {
969 if (callback(key, ctx) == 0)
970 key_free(key);
971 }
972 }
973
974 success = 1;
975
976 error:
977 finish_read_host_files(pvar, 1);
978
979 return (success);
980 }
981
982
983 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
1000 // ���J�������r���s���B
1001 //
1002 // return
1003 // -1 ... �����^������
1004 // 0 ... ����������
1005 // 1 ... ������
1006 int HOSTS_compare_public_key(Key *src, Key *key)
1007 {
1008 int bits;
1009 unsigned char FAR * exp;
1010 unsigned char FAR * mod;
1011 const EC_GROUP *group;
1012 const EC_POINT *pa, *pb;
1013 Key *a, *b;
1014
1015 if (src->type != key->type) {
1016 return -1;
1017 }
1018
1019 switch (key->type) {
1020 case KEY_RSA1: // SSH1 host public key
1021 bits = key->bits;
1022 exp = key->exp;
1023 mod = key->mod;
1024
1025 /* just check for equal exponent and modulus */
1026 return equal_mp_ints(exp, src->exp)
1027 && equal_mp_ints(mod, src->mod);
1028 /*
1029 return equal_mp_ints(exp, pvar->hosts_state.key_exp)
1030 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
1031 */
1032
1033 case KEY_RSA: // SSH2 RSA host public key
1034 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
1038 case KEY_DSA: // SSH2 DSA host public key
1039 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
1045 case KEY_ECDSA256:
1046 case KEY_ECDSA384:
1047 case KEY_ECDSA521:
1048 if (key->ecdsa == NULL || src->ecdsa == NULL) {
1049 return FALSE;
1050 }
1051 group = EC_KEY_get0_group(key->ecdsa);
1052 pa = EC_KEY_get0_public_key(key->ecdsa),
1053 pb = EC_KEY_get0_public_key(src->ecdsa);
1054 return EC_POINT_cmp(group, pa, pb, NULL) == 0;
1055
1056 case KEY_ED25519:
1057 a = key;
1058 b = src;
1059 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
1060 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
1061
1062 default:
1063 return FALSE;
1064 }
1065 }
1066
1067
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 }
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 ssh_keytype type = pvar->hosts_state.hostkey.type;
1144
1145 switch (type) {
1146 case KEY_RSA1:
1147 {
1148 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 break;
1174 }
1175
1176 case KEY_RSA:
1177 case KEY_DSA:
1178 case KEY_ECDSA256:
1179 case KEY_ECDSA384:
1180 case KEY_ECDSA521:
1181 case KEY_ED25519:
1182 {
1183 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 break;
1224 }
1225
1226 default:
1227 return NULL;
1228
1229 }
1230
1231 return result;
1232 }
1233
1234 static char FAR *format_specified_host_key(Key *key, char *hostname, unsigned short tcpport)
1235 {
1236 int host_len = strlen(hostname);
1237 char *result = NULL;
1238 int index;
1239 ssh_keytype type = key->type;
1240
1241 switch (type) {
1242 case KEY_RSA1:
1243 {
1244 int result_len = host_len + 50 + 8 +
1245 get_ushort16_MSBfirst(key->exp) / 3 +
1246 get_ushort16_MSBfirst(key->mod) / 3;
1247 result = (char FAR *) malloc(result_len);
1248
1249 if (tcpport == 22) {
1250 strncpy_s(result, result_len, hostname, _TRUNCATE);
1251 index = host_len;
1252 }
1253 else {
1254 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1255 hostname,
1256 tcpport);
1257 index = strlen(result);
1258 }
1259
1260 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
1261 " %d ", key->bits);
1262 index += strlen(result + index);
1263 index += print_mp_int(result + index, key->exp);
1264 result[index] = ' ';
1265 index++;
1266 index += print_mp_int(result + index, key->mod);
1267 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1268
1269 break;
1270 }
1271
1272 case KEY_RSA:
1273 case KEY_DSA:
1274 case KEY_ECDSA256:
1275 case KEY_ECDSA384:
1276 case KEY_ECDSA521:
1277 case KEY_ED25519:
1278 {
1279 //Key *key = &pvar->hosts_state.hostkey;
1280 char *blob = NULL;
1281 int blen, uulen, msize;
1282 char *uu = NULL;
1283 int n;
1284
1285 key_to_blob(key, &blob, &blen);
1286 uulen = 2 * blen;
1287 uu = malloc(uulen);
1288 if (uu == NULL) {
1289 goto error;
1290 }
1291 n = uuencode(blob, blen, uu, uulen);
1292 if (n > 0) {
1293 msize = host_len + 50 + uulen;
1294 result = malloc(msize);
1295 if (result == NULL) {
1296 goto error;
1297 }
1298
1299 // setup
1300 if (tcpport == 22) {
1301 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1302 hostname,
1303 get_sshname_from_key(key),
1304 uu);
1305 }
1306 else {
1307 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1308 hostname,
1309 tcpport,
1310 get_sshname_from_key(key),
1311 uu);
1312 }
1313 }
1314 error:
1315 if (blob != NULL)
1316 free(blob);
1317 if (uu != NULL)
1318 free(uu);
1319
1320 break;
1321 }
1322
1323 default:
1324 return NULL;
1325
1326 }
1327
1328 return result;
1329 }
1330
1331 static void add_host_key(PTInstVar pvar)
1332 {
1333 char FAR *name = NULL;
1334
1335 if ( pvar->hosts_state.file_names != NULL)
1336 name = pvar->hosts_state.file_names[0];
1337
1338 if (name == NULL || name[0] == 0) {
1339 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1340 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1341 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1342 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1343 } else {
1344 char FAR *keydata = format_host_key(pvar);
1345 int length = strlen(keydata);
1346 int fd;
1347 int amount_written;
1348 int close_result;
1349 char buf[FILENAME_MAX];
1350
1351 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1352 fd = _open(buf,
1353 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1354 _S_IREAD | _S_IWRITE);
1355 if (fd == -1) {
1356 if (errno == EACCES) {
1357 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1358 "An error occurred while trying to write the host key.\n"
1359 "You do not have permission to write to the known-hosts file.");
1360 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1361 } else {
1362 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1363 "An error occurred while trying to write the host key.\n"
1364 "The host key could not be written.");
1365 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1366 }
1367 return;
1368 }
1369
1370 amount_written = _write(fd, keydata, length);
1371 free(keydata);
1372 close_result = _close(fd);
1373
1374 if (amount_written != length || close_result == -1) {
1375 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1376 "An error occurred while trying to write the host key.\n"
1377 "The host key could not be written.");
1378 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1379 }
1380 }
1381 }
1382
1383 // �w�������L�[�� known_hosts �����������B
1384 void HOSTS_add_host_key(PTInstVar pvar, Key *key)
1385 {
1386 char FAR *name = NULL;
1387 char *hostname;
1388 unsigned short tcpport;
1389
1390 hostname = pvar->ssh_state.hostname;
1391 tcpport = pvar->ssh_state.tcpport;
1392
1393 if (pvar->hosts_state.file_names != NULL)
1394 name = pvar->hosts_state.file_names[0];
1395
1396 if (name == NULL || name[0] == 0) {
1397 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1398 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1399 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1400 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1401 }
1402 else {
1403 char FAR *keydata = format_specified_host_key(key, hostname, tcpport);
1404 int length = strlen(keydata);
1405 int fd;
1406 int amount_written;
1407 int close_result;
1408 char buf[FILENAME_MAX];
1409
1410 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1411 fd = _open(buf,
1412 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1413 _S_IREAD | _S_IWRITE);
1414 if (fd == -1) {
1415 if (errno == EACCES) {
1416 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1417 "An error occurred while trying to write the host key.\n"
1418 "You do not have permission to write to the known-hosts file.");
1419 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1420 }
1421 else {
1422 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1423 "An error occurred while trying to write the host key.\n"
1424 "The host key could not be written.");
1425 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1426 }
1427 return;
1428 }
1429
1430 amount_written = _write(fd, keydata, length);
1431 free(keydata);
1432 close_result = _close(fd);
1433
1434 if (amount_written != length || close_result == -1) {
1435 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1436 "An error occurred while trying to write the host key.\n"
1437 "The host key could not be written.");
1438 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1439 }
1440 }
1441 }
1442
1443 static char FAR *copy_mp_int(char FAR * num)
1444 {
1445 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1446 char FAR *result = (char FAR *) malloc(len);
1447
1448 if (result != NULL) {
1449 memcpy(result, num, len);
1450 }
1451
1452 return result;
1453 }
1454
1455 //
1456 // �����z�X�g�����e���������L�[����������
1457 // add_host_key ����������������
1458 //
1459 static void delete_different_key(PTInstVar pvar)
1460 {
1461 char FAR *name = pvar->hosts_state.file_names[0];
1462
1463 if (name == NULL || name[0] == 0) {
1464 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1465 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1466 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1467 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1468 }
1469 else {
1470 Key key; // ���������z�X�g���L�[
1471 Key *key_freed;
1472 int length;
1473 char filename[MAX_PATH];
1474 char tmp[L_tmpnam];
1475 int fd;
1476 int amount_written = 0;
1477 int close_result;
1478 int data_index = 0;
1479 char buf[FILENAME_MAX];
1480
1481 // �������������t�@�C�����J��
1482 _getcwd(filename, sizeof(filename));
1483 tmpnam_s(tmp,sizeof(tmp));
1484 strcat_s(filename, sizeof(filename), tmp);
1485 fd = _open(filename,
1486 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1487 _S_IREAD | _S_IWRITE);
1488
1489 if (fd == -1) {
1490 if (errno == EACCES) {
1491 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1492 "An error occurred while trying to write the host key.\n"
1493 "You do not have permission to write to the known-hosts file.");
1494 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1495 } else {
1496 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1497 "An error occurred while trying to write the host key.\n"
1498 "The host key could not be written.");
1499 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1500 }
1501 return;
1502 }
1503
1504 // ���������T�[�o���L�[����������
1505 memset(&key, 0, sizeof(key));
1506 switch (pvar->hosts_state.hostkey.type) {
1507 case KEY_RSA1: // SSH1
1508 key.type = KEY_RSA1;
1509 key.bits = pvar->hosts_state.hostkey.bits;
1510 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1511 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1512 break;
1513 case KEY_RSA: // SSH2 RSA
1514 key.type = KEY_RSA;
1515 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1516 break;
1517 case KEY_DSA: // SSH2 DSA
1518 key.type = KEY_DSA;
1519 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1520 break;
1521 case KEY_ECDSA256:
1522 case KEY_ECDSA384:
1523 case KEY_ECDSA521:
1524 key.type = pvar->hosts_state.hostkey.type;
1525 key.ecdsa = EC_KEY_dup(pvar->hosts_state.hostkey.ecdsa);
1526 break;
1527 case KEY_ED25519:
1528 key.type = pvar->hosts_state.hostkey.type;
1529 key.ed25519_pk = duplicate_ED25519_PK(pvar->hosts_state.hostkey.ed25519_pk);
1530 break;
1531 }
1532
1533 // �t�@�C��������������
1534 begin_read_host_files(pvar, 0);
1535 do {
1536 int host_index = 0;
1537 int matched = 0;
1538 int keybits = 0;
1539 char FAR *data;
1540 int do_write = 0;
1541 length = amount_written = 0;
1542
1543 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1544 break;
1545 }
1546
1547 if (data_index == pvar->hosts_state.file_data_index) {
1548 // index ���i������ == ��������������
1549 break;
1550 }
1551
1552 data = pvar->hosts_state.file_data + data_index;
1553 host_index = eat_spaces(data);
1554
1555 if (data[host_index] == '#') {
1556 do_write = 1;
1557 }
1558 else {
1559 // �z�X�g������
1560 host_index--;
1561 do {
1562 int negated;
1563 int bracketed;
1564 char *end_bracket;
1565 int host_matched = 0;
1566 unsigned short keyfile_port = 22;
1567
1568 host_index++;
1569 negated = data[host_index] == '!';
1570
1571 if (negated) {
1572 host_index++;
1573 bracketed = data[host_index] == '[';
1574 if (bracketed) {
1575 end_bracket = strstr(data + host_index + 1, "]:");
1576 if (end_bracket != NULL) {
1577 *end_bracket = ' ';
1578 host_index++;
1579 }
1580 }
1581 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1582 if (bracketed && end_bracket != NULL) {
1583 *end_bracket = ']';
1584 keyfile_port = atoi(end_bracket + 2);
1585 }
1586 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1587 matched = 0;
1588 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1589 host_index--;
1590 do {
1591 host_index++;
1592 host_index += eat_to_end_of_pattern(data + host_index);
1593 } while (data[host_index] == ',');
1594 break;
1595 }
1596 }
1597 else {
1598 bracketed = data[host_index] == '[';
1599 if (bracketed) {
1600 end_bracket = strstr(data + host_index + 1, "]:");
1601 if (end_bracket != NULL) {
1602 *end_bracket = ' ';
1603 host_index++;
1604 }
1605 }
1606 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1607 if (bracketed && end_bracket != NULL) {
1608 *end_bracket = ']';
1609 keyfile_port = atoi(end_bracket + 2);
1610 }
1611 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1612 matched = 1;
1613 }
1614 }
1615 host_index += eat_to_end_of_pattern(data + host_index);
1616 } while (data[host_index] == ',');
1617
1618 // �z�X�g������������
1619 if (!matched) {
1620 do_write = 1;
1621 }
1622 // �z�X�g��������
1623 else {
1624 // �����`�������� or ���v�����L�[
1625 if (match_key(pvar, &key) != 0) {
1626 do_write = 1;
1627 }
1628 // �����`�������������v�������L�[���X�L�b�v������
1629 }
1630 }
1631
1632 // ������������
1633 if (do_write) {
1634 length = pvar->hosts_state.file_data_index - data_index;
1635 amount_written =
1636 _write(fd, pvar->hosts_state.file_data + data_index,
1637 length);
1638
1639 if (amount_written != length) {
1640 goto error1;
1641 }
1642 }
1643 data_index = pvar->hosts_state.file_data_index;
1644 } while (1); // ������������
1645
1646 error1:
1647 close_result = _close(fd);
1648 if (amount_written != length || close_result == -1) {
1649 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1650 "An error occurred while trying to write the host key.\n"
1651 "The host key could not be written.");
1652 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1653 goto error2;
1654 }
1655
1656 // �������������t�@�C���������l�[��
1657 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1658 _unlink(buf);
1659 rename(filename, buf);
1660
1661 error2:
1662 _unlink(filename);
1663
1664 finish_read_host_files(pvar, 0);
1665
1666 // ���������������������������B
1667 key_freed = key_new(KEY_UNSPEC);
1668 memcpy(key_freed, &key, sizeof(Key));
1669 key_free(key_freed);
1670 }
1671 }
1672
1673
1674 void HOSTS_delete_all_hostkeys(PTInstVar pvar)
1675 {
1676 char FAR *name = pvar->hosts_state.file_names[0];
1677 char *hostname;
1678 unsigned short tcpport;
1679
1680 hostname = pvar->ssh_state.hostname;
1681 tcpport = pvar->ssh_state.tcpport;
1682
1683 if (name == NULL || name[0] == 0) {
1684 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1685 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1686 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1687 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1688 }
1689 else {
1690 Key key; // ���������z�X�g���L�[
1691 Key *key_freed;
1692 int length;
1693 char filename[MAX_PATH];
1694 char tmp[L_tmpnam];
1695 int fd;
1696 int amount_written = 0;
1697 int close_result;
1698 int data_index = 0;
1699 char buf[FILENAME_MAX];
1700
1701 // �������������t�@�C�����J��
1702 _getcwd(filename, sizeof(filename));
1703 tmpnam_s(tmp, sizeof(tmp));
1704 strcat_s(filename, sizeof(filename), tmp);
1705 fd = _open(filename,
1706 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1707 _S_IREAD | _S_IWRITE);
1708
1709 if (fd == -1) {
1710 if (errno == EACCES) {
1711 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1712 "An error occurred while trying to write the host key.\n"
1713 "You do not have permission to write to the known-hosts file.");
1714 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1715 }
1716 else {
1717 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1718 "An error occurred while trying to write the host key.\n"
1719 "The host key could not be written.");
1720 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1721 }
1722 return;
1723 }
1724
1725 // ���������T�[�o���L�[����������
1726 memset(&key, 0, sizeof(key));
1727 switch (pvar->hosts_state.hostkey.type) {
1728 case KEY_RSA1: // SSH1
1729 key.type = KEY_RSA1;
1730 key.bits = pvar->hosts_state.hostkey.bits;
1731 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1732 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1733 break;
1734 case KEY_RSA: // SSH2 RSA
1735 key.type = KEY_RSA;
1736 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1737 break;
1738 case KEY_DSA: // SSH2 DSA
1739 key.type = KEY_DSA;
1740 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1741 break;
1742 case KEY_ECDSA256:
1743 case KEY_ECDSA384:
1744 case KEY_ECDSA521:
1745 key.type = pvar->hosts_state.hostkey.type;
1746 key.ecdsa = EC_KEY_dup(pvar->hosts_state.hostkey.ecdsa);
1747 break;
1748 case KEY_ED25519:
1749 key.type = pvar->hosts_state.hostkey.type;
1750 key.ed25519_pk = duplicate_ED25519_PK(pvar->hosts_state.hostkey.ed25519_pk);
1751 break;
1752 }
1753
1754 // �t�@�C��������������
1755 begin_read_host_files(pvar, 0);
1756 do {
1757 int host_index = 0;
1758 int matched = 0;
1759 int keybits = 0;
1760 char FAR *data;
1761 int do_write = 0;
1762 length = amount_written = 0;
1763
1764 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1765 break;
1766 }
1767
1768 if (data_index == pvar->hosts_state.file_data_index) {
1769 // index ���i������ == ��������������
1770 break;
1771 }
1772
1773 data = pvar->hosts_state.file_data + data_index;
1774 host_index = eat_spaces(data);
1775
1776 if (data[host_index] == '#') {
1777 do_write = 1;
1778 }
1779 else {
1780 // �z�X�g������
1781 host_index--;
1782 do {
1783 int negated;
1784 int bracketed;
1785 char *end_bracket;
1786 int host_matched = 0;
1787 unsigned short keyfile_port = 22;
1788
1789 host_index++;
1790 negated = data[host_index] == '!';
1791
1792 if (negated) {
1793 host_index++;
1794 bracketed = data[host_index] == '[';
1795 if (bracketed) {
1796 end_bracket = strstr(data + host_index + 1, "]:");
1797 if (end_bracket != NULL) {
1798 *end_bracket = ' ';
1799 host_index++;
1800 }
1801 }
1802 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1803 if (bracketed && end_bracket != NULL) {
1804 *end_bracket = ']';
1805 keyfile_port = atoi(end_bracket + 2);
1806 }
1807 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1808 matched = 0;
1809 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1810 host_index--;
1811 do {
1812 host_index++;
1813 host_index += eat_to_end_of_pattern(data + host_index);
1814 } while (data[host_index] == ',');
1815 break;
1816 }
1817 }
1818 else {
1819 bracketed = data[host_index] == '[';
1820 if (bracketed) {
1821 end_bracket = strstr(data + host_index + 1, "]:");
1822 if (end_bracket != NULL) {
1823 *end_bracket = ' ';
1824 host_index++;
1825 }
1826 }
1827 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1828 if (bracketed && end_bracket != NULL) {
1829 *end_bracket = ']';
1830 keyfile_port = atoi(end_bracket + 2);
1831 }
1832 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1833 matched = 1;
1834 }
1835 }
1836 host_index += eat_to_end_of_pattern(data + host_index);
1837 } while (data[host_index] == ',');
1838
1839 // �z�X�g������������
1840 if (!matched) {
1841 do_write = 1;
1842 }
1843 // �z�X�g��������
1844 else {
1845 // ���������������������B
1846
1847 }
1848 }
1849
1850 // ������������
1851 if (do_write) {
1852 length = pvar->hosts_state.file_data_index - data_index;
1853 amount_written =
1854 _write(fd, pvar->hosts_state.file_data + data_index,
1855 length);
1856
1857 if (amount_written != length) {
1858 goto error1;
1859 }
1860 }
1861 data_index = pvar->hosts_state.file_data_index;
1862 } while (1); // ������������
1863
1864 error1:
1865 close_result = _close(fd);
1866 if (amount_written != length || close_result == -1) {
1867 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1868 "An error occurred while trying to write the host key.\n"
1869 "The host key could not be written.");
1870 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1871 goto error2;
1872 }
1873
1874 // �������������t�@�C���������l�[��
1875 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1876 _unlink(buf);
1877 rename(filename, buf);
1878
1879 error2:
1880 _unlink(filename);
1881
1882 finish_read_host_files(pvar, 0);
1883
1884 // ���������������������������B
1885 key_freed = key_new(KEY_UNSPEC);
1886 memcpy(key_freed, &key, sizeof(Key));
1887 key_free(key_freed);
1888 }
1889 }
1890
1891
1892 //
1893 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1894 // ���[�U���m�F�������B
1895 // TODO: finger print���\�����s���B
1896 // (2006.3.25 yutaka)
1897 //
1898 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1899 LPARAM lParam)
1900 {
1901 PTInstVar pvar;
1902 LOGFONT logfont;
1903 HFONT font;
1904 char uimsg[MAX_UIMSG];
1905
1906 switch (msg) {
1907 case WM_INITDIALOG:
1908 pvar = (PTInstVar) lParam;
1909 pvar->hosts_state.hosts_dialog = dlg;
1910 SetWindowLong(dlg, DWL_USER, lParam);
1911
1912 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1913 GetWindowText(dlg, uimsg, sizeof(uimsg));
1914 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1915 SetWindowText(dlg, pvar->ts->UIMsg);
1916 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1917 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING", pvar, uimsg);
1918 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1919 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1920 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING2", pvar, uimsg);
1921 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1922 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1923 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1924 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1925 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1926 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1927 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1928 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1929 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1930 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1931 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1932 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1933 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1934
1935 switch (pvar->dns_key_check) {
1936 case DNS_VERIFY_NOTFOUND:
1937 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1938 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1939 break;
1940 case DNS_VERIFY_MATCH:
1941 case DNS_VERIFY_AUTH_MATCH:
1942 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1943 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1944 break;
1945 case DNS_VERIFY_MISMATCH:
1946 case DNS_VERIFY_AUTH_MISMATCH:
1947 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1948 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1949 break;
1950 case DNS_VERIFY_DIFFERENTTYPE:
1951 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1952 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1953 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1954 break;
1955 }
1956
1957 switch (pvar->dns_key_check) {
1958 case DNS_VERIFY_MATCH:
1959 case DNS_VERIFY_MISMATCH:
1960 case DNS_VERIFY_DIFFERENTTYPE:
1961 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1962 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1963 break;
1964 case DNS_VERIFY_AUTH_MATCH:
1965 case DNS_VERIFY_AUTH_MISMATCH:
1966 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1967 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1968 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1969 break;
1970 }
1971
1972 init_hosts_dlg(pvar, dlg);
1973
1974 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1975 GetObject(font, sizeof(LOGFONT), &logfont);
1976 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1977 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1978 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1979 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1980 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1981 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1982 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1983 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1984 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1985 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1986 }
1987 else {
1988 DlgHostsAddFont = NULL;
1989 }
1990
1991 // add host check box���`�F�b�N���f�t�H���g������������
1992 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1993
1994 return TRUE; /* because we do not set the focus */
1995
1996 case WM_COMMAND:
1997 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1998
1999 switch (LOWORD(wParam)) {
2000 case IDC_CONTINUE:
2001 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2002 if (!pvar->cv->Ready) {
2003 goto canceled;
2004 }
2005
2006 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2007 add_host_key(pvar);
2008 }
2009
2010 if (SSHv1(pvar)) {
2011 SSH_notify_host_OK(pvar);
2012 } else { // SSH2
2013 // SSH2���������� SSH_notify_host_OK() �������B
2014 }
2015
2016 pvar->hosts_state.hosts_dialog = NULL;
2017
2018 EndDialog(dlg, 1);
2019
2020 if (DlgHostsAddFont != NULL) {
2021 DeleteObject(DlgHostsAddFont);
2022 }
2023
2024 return TRUE;
2025
2026 case IDCANCEL: /* kill the connection */
2027 canceled:
2028 pvar->hosts_state.hosts_dialog = NULL;
2029 notify_closed_connection(pvar, "authentication cancelled");
2030 EndDialog(dlg, 0);
2031
2032 if (DlgHostsAddFont != NULL) {
2033 DeleteObject(DlgHostsAddFont);
2034 }
2035
2036 return TRUE;
2037
2038 default:
2039 return FALSE;
2040 }
2041
2042 default:
2043 return FALSE;
2044 }
2045 }
2046
2047 //
2048 // �u�����������m�F�_�C�A���O������
2049 //
2050 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2051 LPARAM lParam)
2052 {
2053 PTInstVar pvar;
2054 LOGFONT logfont;
2055 HFONT font;
2056 char uimsg[MAX_UIMSG];
2057
2058 switch (msg) {
2059 case WM_INITDIALOG:
2060 pvar = (PTInstVar) lParam;
2061 pvar->hosts_state.hosts_dialog = dlg;
2062 SetWindowLong(dlg, DWL_USER, lParam);
2063
2064 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2065 GetWindowText(dlg, uimsg, sizeof(uimsg));
2066 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
2067 SetWindowText(dlg, pvar->ts->UIMsg);
2068 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
2069 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
2070 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2071 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2072 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
2073 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2074 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2075 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
2076 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2077 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2078 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
2079 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2080 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2081 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2082 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2083 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2084 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2085 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2086
2087 switch (pvar->dns_key_check) {
2088 case DNS_VERIFY_NOTFOUND:
2089 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2090 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2091 break;
2092 case DNS_VERIFY_MATCH:
2093 case DNS_VERIFY_AUTH_MATCH:
2094 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2095 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2096 break;
2097 case DNS_VERIFY_MISMATCH:
2098 case DNS_VERIFY_AUTH_MISMATCH:
2099 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2100 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2101 break;
2102 case DNS_VERIFY_DIFFERENTTYPE:
2103 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2104 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2105 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2106 break;
2107 }
2108
2109 switch (pvar->dns_key_check) {
2110 case DNS_VERIFY_MATCH:
2111 case DNS_VERIFY_MISMATCH:
2112 case DNS_VERIFY_DIFFERENTTYPE:
2113 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2114 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2115 break;
2116 case DNS_VERIFY_AUTH_MATCH:
2117 case DNS_VERIFY_AUTH_MISMATCH:
2118 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2119 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2120 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2121 break;
2122 }
2123
2124 init_hosts_dlg(pvar, dlg);
2125
2126 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2127 GetObject(font, sizeof(LOGFONT), &logfont);
2128 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
2129 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2130 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2131 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2132 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2133 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2134 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2135 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2136 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2137 }
2138 else {
2139 DlgHostsReplaceFont = NULL;
2140 }
2141
2142 // �f�t�H���g���`�F�b�N����������
2143 return TRUE; /* because we do not set the focus */
2144
2145 case WM_COMMAND:
2146 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2147
2148 switch (LOWORD(wParam)) {
2149 case IDC_CONTINUE:
2150 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2151 if (!pvar->cv->Ready) {
2152 goto canceled;
2153 }
2154
2155 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2156 add_host_key(pvar);
2157 delete_different_key(pvar);
2158 }
2159
2160 if (SSHv1(pvar)) {
2161 SSH_notify_host_OK(pvar);
2162 } else { // SSH2
2163 // SSH2���������� SSH_notify_host_OK() �������B
2164 }
2165
2166 pvar->hosts_state.hosts_dialog = NULL;
2167
2168 EndDialog(dlg, 1);
2169
2170 if (DlgHostsReplaceFont != NULL) {
2171 DeleteObject(DlgHostsReplaceFont);
2172 }
2173
2174 return TRUE;
2175
2176 case IDCANCEL: /* kill the connection */
2177 canceled:
2178 pvar->hosts_state.hosts_dialog = NULL;
2179 notify_closed_connection(pvar, "authentication cancelled");
2180 EndDialog(dlg, 0);
2181
2182 if (DlgHostsReplaceFont != NULL) {
2183 DeleteObject(DlgHostsReplaceFont);
2184 }
2185
2186 return TRUE;
2187
2188 default:
2189 return FALSE;
2190 }
2191
2192 default:
2193 return FALSE;
2194 }
2195 }
2196
2197 //
2198 // �����z�X�g�����`�����������������m�F�_�C�A���O������
2199 //
2200 static BOOL CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2201 LPARAM lParam)
2202 {
2203 PTInstVar pvar;
2204 LOGFONT logfont;
2205 HFONT font;
2206 char uimsg[MAX_UIMSG];
2207
2208 switch (msg) {
2209 case WM_INITDIALOG:
2210 pvar = (PTInstVar) lParam;
2211 pvar->hosts_state.hosts_dialog = dlg;
2212 SetWindowLong(dlg, DWL_USER, lParam);
2213
2214 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2215 GetWindowText(dlg, uimsg, sizeof(uimsg));
2216 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
2217 SetWindowText(dlg, pvar->ts->UIMsg);
2218 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
2219 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
2220 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2221 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2222 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
2223 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2224 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2225 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
2226 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2227 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2228 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
2229 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2230 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2231 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2232 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2233 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2234 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2235 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2236
2237 switch (pvar->dns_key_check) {
2238 case DNS_VERIFY_NOTFOUND:
2239 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2240 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2241 break;
2242 case DNS_VERIFY_MATCH:
2243 case DNS_VERIFY_AUTH_MATCH:
2244 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2245 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2246 break;
2247 case DNS_VERIFY_MISMATCH:
2248 case DNS_VERIFY_AUTH_MISMATCH:
2249 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2250 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2251 break;
2252 case DNS_VERIFY_DIFFERENTTYPE:
2253 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2254 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2255 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2256 break;
2257 }
2258
2259 switch (pvar->dns_key_check) {
2260 case DNS_VERIFY_MATCH:
2261 case DNS_VERIFY_MISMATCH:
2262 case DNS_VERIFY_DIFFERENTTYPE:
2263 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2264 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2265 break;
2266 case DNS_VERIFY_AUTH_MATCH:
2267 case DNS_VERIFY_AUTH_MISMATCH:
2268 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2269 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2270 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2271 break;
2272 }
2273
2274 init_hosts_dlg(pvar, dlg);
2275
2276 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2277 GetObject(font, sizeof(LOGFONT), &logfont);
2278 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
2279 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2280 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2281 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2282 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2283 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2284 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2285 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2286 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2287 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2288 }
2289 else {
2290 DlgHostsAddFont = NULL;
2291 }
2292
2293 // add host check box ���f�t�H���g�� off ������
2294 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
2295
2296 return TRUE; /* because we do not set the focus */
2297
2298 case WM_COMMAND:
2299 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2300
2301 switch (LOWORD(wParam)) {
2302 case IDC_CONTINUE:
2303 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2304 if (!pvar->cv->Ready) {
2305 goto canceled;
2306 }
2307
2308 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2309 add_host_key(pvar);
2310 }
2311
2312 if (SSHv1(pvar)) {
2313 SSH_notify_host_OK(pvar);
2314 } else { // SSH2
2315 // SSH2���������� SSH_notify_host_OK() �������B
2316 }
2317
2318 pvar->hosts_state.hosts_dialog = NULL;
2319
2320 EndDialog(dlg, 1);
2321
2322 if (DlgHostsAddFont != NULL) {
2323 DeleteObject(DlgHostsAddFont);
2324 }
2325
2326 return TRUE;
2327
2328 case IDCANCEL: /* kill the connection */
2329 canceled:
2330 pvar->hosts_state.hosts_dialog = NULL;
2331 notify_closed_connection(pvar, "authentication cancelled");
2332 EndDialog(dlg, 0);
2333
2334 if (DlgHostsAddFont != NULL) {
2335 DeleteObject(DlgHostsAddFont);
2336 }
2337
2338 return TRUE;
2339
2340 default:
2341 return FALSE;
2342 }
2343
2344 default:
2345 return FALSE;
2346 }
2347 }
2348
2349 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
2350 {
2351 if (pvar->hosts_state.hosts_dialog == NULL) {
2352 HWND cur_active = GetActiveWindow();
2353
2354 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
2355 cur_active != NULL ? cur_active : wnd,
2356 hosts_add_dlg_proc, (LPARAM) pvar);
2357 }
2358 }
2359
2360 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
2361 {
2362 if (pvar->hosts_state.hosts_dialog == NULL) {
2363 HWND cur_active = GetActiveWindow();
2364
2365 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
2366 cur_active != NULL ? cur_active : wnd,
2367 hosts_replace_dlg_proc, (LPARAM) pvar);
2368 }
2369 }
2370
2371 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
2372 {
2373 if (pvar->hosts_state.hosts_dialog == NULL) {
2374 HWND cur_active = GetActiveWindow();
2375
2376 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2377 cur_active != NULL ? cur_active : wnd,
2378 hosts_add2_dlg_proc, (LPARAM) pvar);
2379 }
2380 }
2381
2382 //
2383 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
2384 //
2385 // SSH2���������� (2006.3.24 yutaka)
2386 //
2387 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
2388 {
2389 int found_different_key = 0, found_different_type_key = 0;
2390
2391 pvar->dns_key_check = DNS_VERIFY_NONE;
2392
2393 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
2394 if (pvar->hosts_state.prefetched_hostname != NULL
2395 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
2396 && match_key(pvar, key) == 1) {
2397
2398 if (SSHv1(pvar)) {
2399 SSH_notify_host_OK(pvar);
2400 } else {
2401 // SSH2���������� SSH_notify_host_OK() �������B
2402 }
2403 return TRUE;
2404 }
2405
2406 // �������������������������A�������_���t�@�C��������������
2407 if (begin_read_host_files(pvar, 0)) {
2408 do {
2409 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
2410 break;
2411 }
2412
2413 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
2414 int match = match_key(pvar, key);
2415 if (match == 1) {
2416 finish_read_host_files(pvar, 0);
2417 // ���������G���g�����Q�������A���v�����L�[�������������������B
2418 // SSH2���������������������������B(2006.3.29 yutaka)
2419 if (SSHv1(pvar)) {
2420 SSH_notify_host_OK(pvar);
2421 } else {
2422 // SSH2���������� SSH_notify_host_OK() �������B
2423 }
2424 return TRUE;
2425 }
2426 else if (match == 0) {
2427 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2428 found_different_key = 1;
2429 }
2430 else {
2431 // �L�[���`������������
2432 found_different_type_key = 1;
2433 }
2434 }
2435 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2436
2437 finish_read_host_files(pvar, 0);
2438 }
2439
2440 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2441 pvar->hosts_state.hostkey.type = key->type;
2442 switch (key->type) {
2443 case KEY_RSA1: // SSH1
2444 pvar->hosts_state.hostkey.bits = key->bits;
2445 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
2446 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
2447 break;
2448 case KEY_RSA: // SSH2 RSA
2449 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
2450 break;
2451 case KEY_DSA: // SSH2 DSA
2452 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
2453 break;
2454 case KEY_ECDSA256: // SSH2 ECDSA
2455 case KEY_ECDSA384:
2456 case KEY_ECDSA521:
2457 pvar->hosts_state.hostkey.ecdsa = EC_KEY_dup(key->ecdsa);
2458 break;
2459 case KEY_ED25519:
2460 pvar->hosts_state.hostkey.ed25519_pk = duplicate_ED25519_PK(key->ed25519_pk);
2461 break;
2462 }
2463 free(pvar->hosts_state.prefetched_hostname);
2464 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2465
2466 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2467 if (pvar->nocheck_known_hosts == TRUE) {
2468 return TRUE;
2469 }
2470
2471 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2472 pvar->dns_key_check = verify_hostkey_dns(hostname, key);
2473 }
2474
2475 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
2476 // �������K�v�����������A�����R�[�������X�����B
2477 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
2478 // (2007.10.1 yutaka)
2479 if (found_different_key) {
2480 HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar);
2481 }
2482 else if (found_different_type_key) {
2483 HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar);
2484 }
2485 else {
2486 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
2487 }
2488
2489 return TRUE;
2490 }
2491
2492 void HOSTS_notify_disconnecting(PTInstVar pvar)
2493 {
2494 if (pvar->hosts_state.hosts_dialog != NULL) {
2495 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
2496 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
2497 EnableWindow(pvar->NotificationWindow, TRUE);
2498 }
2499 }
2500
2501 void HOSTS_end(PTInstVar pvar)
2502 {
2503 int i;
2504
2505 free(pvar->hosts_state.prefetched_hostname);
2506 init_hostkey(&pvar->hosts_state.hostkey);
2507
2508 if (pvar->hosts_state.file_names != NULL) {
2509 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
2510 free(pvar->hosts_state.file_names[i]);
2511 }
2512 free(pvar->hosts_state.file_names);
2513 }
2514 }

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