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

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