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 6152 - (show annotations) (download) (as text)
Wed Nov 18 13:11:56 2015 UTC (8 years, 4 months ago) by maya
File MIME type: text/x-csrc
File size: 70771 byte(s)
鍵の置き換え・Hostkey Rotationの更新後に About TTSSH ダイアログを表示すると落ちる問題を修正
  hosts_state.hostkey を 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 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 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
1058 free(fp);
1059 break;
1060 case SSH_DIGEST_SHA256:
1061 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_BASE64, dgst_alg);
1062 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
1063 free(fp);
1064 break;
1065 }
1066
1067 // �r�W���A����fingerprint���\������
1068 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART, dgst_alg);
1069 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
1070 free(fp);
1071 }
1072
1073 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
1074 {
1075 char buf[1024];
1076 char buf2[2048];
1077 int i, j;
1078 int ch;
1079
1080 // static text�� # �������z�X�g�����u������
1081 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
1082 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
1083 buf2[i] = ch;
1084 }
1085 strncpy_s(buf2 + i, sizeof(buf2) - i,
1086 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
1087 j = i + strlen(buf2 + i);
1088 for (; buf[i] == '#'; i++) {
1089 }
1090 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
1091
1092 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
1093
1094 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
1095
1096 CheckDlgButton(dlg, IDC_FP_HASH_ALG_SHA256, TRUE);
1097 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
1098 }
1099
1100 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
1101 {
1102 int i = 0, j, k;
1103 BIGNUM *num = BN_new();
1104 int ch;
1105
1106 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
1107
1108 do {
1109 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
1110 i++;
1111 } while (!BN_is_zero(num));
1112
1113 /* we need to reverse the digits */
1114 for (j = 0, k = i - 1; j < k; j++, k--) {
1115 ch = buf[j];
1116 buf[j] = buf[k];
1117 buf[k] = ch;
1118 }
1119
1120 buf[i] = 0;
1121 return i;
1122 }
1123
1124 //
1125 // known_hosts �t�@�C�������������G���g�������������B
1126 //
1127 static char FAR *format_host_key(PTInstVar pvar)
1128 {
1129 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
1130 char *result = NULL;
1131 int index;
1132 ssh_keytype type = pvar->hosts_state.hostkey.type;
1133
1134 switch (type) {
1135 case KEY_RSA1:
1136 {
1137 int result_len = host_len + 50 + 8 +
1138 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
1139 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
1140 result = (char FAR *) malloc(result_len);
1141
1142 if (pvar->ssh_state.tcpport == 22) {
1143 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
1144 index = host_len;
1145 }
1146 else {
1147 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1148 pvar->hosts_state.prefetched_hostname,
1149 pvar->ssh_state.tcpport);
1150 index = strlen(result);
1151 }
1152
1153 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
1154 " %d ", pvar->hosts_state.hostkey.bits);
1155 index += strlen(result + index);
1156 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
1157 result[index] = ' ';
1158 index++;
1159 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
1160 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1161
1162 break;
1163 }
1164
1165 case KEY_RSA:
1166 case KEY_DSA:
1167 case KEY_ECDSA256:
1168 case KEY_ECDSA384:
1169 case KEY_ECDSA521:
1170 case KEY_ED25519:
1171 {
1172 Key *key = &pvar->hosts_state.hostkey;
1173 char *blob = NULL;
1174 int blen, uulen, msize;
1175 char *uu = NULL;
1176 int n;
1177
1178 key_to_blob(key, &blob, &blen);
1179 uulen = 2 * blen;
1180 uu = malloc(uulen);
1181 if (uu == NULL) {
1182 goto error;
1183 }
1184 n = uuencode(blob, blen, uu, uulen);
1185 if (n > 0) {
1186 msize = host_len + 50 + uulen;
1187 result = malloc(msize);
1188 if (result == NULL) {
1189 goto error;
1190 }
1191
1192 // setup
1193 if (pvar->ssh_state.tcpport == 22) {
1194 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1195 pvar->hosts_state.prefetched_hostname,
1196 get_sshname_from_key(key),
1197 uu);
1198 } else {
1199 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1200 pvar->hosts_state.prefetched_hostname,
1201 pvar->ssh_state.tcpport,
1202 get_sshname_from_key(key),
1203 uu);
1204 }
1205 }
1206 error:
1207 if (blob != NULL)
1208 free(blob);
1209 if (uu != NULL)
1210 free(uu);
1211
1212 break;
1213 }
1214
1215 default:
1216 return NULL;
1217
1218 }
1219
1220 return result;
1221 }
1222
1223 static char FAR *format_specified_host_key(Key *key, char *hostname, unsigned short tcpport)
1224 {
1225 int host_len = strlen(hostname);
1226 char *result = NULL;
1227 int index;
1228 ssh_keytype type = key->type;
1229
1230 switch (type) {
1231 case KEY_RSA1:
1232 {
1233 int result_len = host_len + 50 + 8 +
1234 get_ushort16_MSBfirst(key->exp) / 3 +
1235 get_ushort16_MSBfirst(key->mod) / 3;
1236 result = (char FAR *) malloc(result_len);
1237
1238 if (tcpport == 22) {
1239 strncpy_s(result, result_len, hostname, _TRUNCATE);
1240 index = host_len;
1241 }
1242 else {
1243 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1244 hostname,
1245 tcpport);
1246 index = strlen(result);
1247 }
1248
1249 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
1250 " %d ", key->bits);
1251 index += strlen(result + index);
1252 index += print_mp_int(result + index, key->exp);
1253 result[index] = ' ';
1254 index++;
1255 index += print_mp_int(result + index, key->mod);
1256 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1257
1258 break;
1259 }
1260
1261 case KEY_RSA:
1262 case KEY_DSA:
1263 case KEY_ECDSA256:
1264 case KEY_ECDSA384:
1265 case KEY_ECDSA521:
1266 case KEY_ED25519:
1267 {
1268 //Key *key = &pvar->hosts_state.hostkey;
1269 char *blob = NULL;
1270 int blen, uulen, msize;
1271 char *uu = NULL;
1272 int n;
1273
1274 key_to_blob(key, &blob, &blen);
1275 uulen = 2 * blen;
1276 uu = malloc(uulen);
1277 if (uu == NULL) {
1278 goto error;
1279 }
1280 n = uuencode(blob, blen, uu, uulen);
1281 if (n > 0) {
1282 msize = host_len + 50 + uulen;
1283 result = malloc(msize);
1284 if (result == NULL) {
1285 goto error;
1286 }
1287
1288 // setup
1289 if (tcpport == 22) {
1290 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1291 hostname,
1292 get_sshname_from_key(key),
1293 uu);
1294 }
1295 else {
1296 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1297 hostname,
1298 tcpport,
1299 get_sshname_from_key(key),
1300 uu);
1301 }
1302 }
1303 error:
1304 if (blob != NULL)
1305 free(blob);
1306 if (uu != NULL)
1307 free(uu);
1308
1309 break;
1310 }
1311
1312 default:
1313 return NULL;
1314
1315 }
1316
1317 return result;
1318 }
1319
1320 static void add_host_key(PTInstVar pvar)
1321 {
1322 char FAR *name = NULL;
1323
1324 if ( pvar->hosts_state.file_names != NULL)
1325 name = pvar->hosts_state.file_names[0];
1326
1327 if (name == NULL || name[0] == 0) {
1328 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1329 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1330 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1331 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1332 } else {
1333 char FAR *keydata = format_host_key(pvar);
1334 int length = strlen(keydata);
1335 int fd;
1336 int amount_written;
1337 int close_result;
1338 char buf[FILENAME_MAX];
1339
1340 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1341 fd = _open(buf,
1342 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1343 _S_IREAD | _S_IWRITE);
1344 if (fd == -1) {
1345 if (errno == EACCES) {
1346 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1347 "An error occurred while trying to write the host key.\n"
1348 "You do not have permission to write to the known-hosts file.");
1349 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1350 } else {
1351 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1352 "An error occurred while trying to write the host key.\n"
1353 "The host key could not be written.");
1354 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1355 }
1356 return;
1357 }
1358
1359 amount_written = _write(fd, keydata, length);
1360 free(keydata);
1361 close_result = _close(fd);
1362
1363 if (amount_written != length || close_result == -1) {
1364 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1365 "An error occurred while trying to write the host key.\n"
1366 "The host key could not be written.");
1367 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1368 }
1369 }
1370 }
1371
1372 // �w�������L�[�� known_hosts �����������B
1373 void HOSTS_add_host_key(PTInstVar pvar, Key *key)
1374 {
1375 char FAR *name = NULL;
1376 char *hostname;
1377 unsigned short tcpport;
1378
1379 hostname = pvar->ssh_state.hostname;
1380 tcpport = pvar->ssh_state.tcpport;
1381
1382 if (pvar->hosts_state.file_names != NULL)
1383 name = pvar->hosts_state.file_names[0];
1384
1385 if (name == NULL || name[0] == 0) {
1386 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1387 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1388 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1389 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1390 }
1391 else {
1392 char FAR *keydata = format_specified_host_key(key, hostname, tcpport);
1393 int length = strlen(keydata);
1394 int fd;
1395 int amount_written;
1396 int close_result;
1397 char buf[FILENAME_MAX];
1398
1399 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1400 fd = _open(buf,
1401 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1402 _S_IREAD | _S_IWRITE);
1403 if (fd == -1) {
1404 if (errno == EACCES) {
1405 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1406 "An error occurred while trying to write the host key.\n"
1407 "You do not have permission to write to the known-hosts file.");
1408 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1409 }
1410 else {
1411 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1412 "An error occurred while trying to write the host key.\n"
1413 "The host key could not be written.");
1414 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1415 }
1416 return;
1417 }
1418
1419 amount_written = _write(fd, keydata, length);
1420 free(keydata);
1421 close_result = _close(fd);
1422
1423 if (amount_written != length || close_result == -1) {
1424 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1425 "An error occurred while trying to write the host key.\n"
1426 "The host key could not be written.");
1427 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1428 }
1429 }
1430 }
1431
1432 //
1433 // �����z�X�g�����e���������L�[����������
1434 // add_host_key ����������������
1435 //
1436 static void delete_different_key(PTInstVar pvar)
1437 {
1438 char FAR *name = pvar->hosts_state.file_names[0];
1439
1440 if (name == NULL || name[0] == 0) {
1441 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1442 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1443 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1444 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1445 }
1446 else {
1447 Key key; // known_hosts���o�^������������
1448 int length;
1449 char filename[MAX_PATH];
1450 char tmp[L_tmpnam];
1451 int fd;
1452 int amount_written = 0;
1453 int close_result;
1454 int data_index = 0;
1455 char buf[FILENAME_MAX];
1456
1457 // �������������t�@�C�����J��
1458 _getcwd(filename, sizeof(filename));
1459 tmpnam_s(tmp,sizeof(tmp));
1460 strcat_s(filename, sizeof(filename), tmp);
1461 fd = _open(filename,
1462 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1463 _S_IREAD | _S_IWRITE);
1464
1465 if (fd == -1) {
1466 if (errno == EACCES) {
1467 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1468 "An error occurred while trying to write the host key.\n"
1469 "You do not have permission to write to the known-hosts file.");
1470 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1471 } else {
1472 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1473 "An error occurred while trying to write the host key.\n"
1474 "The host key could not be written.");
1475 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1476 }
1477 return;
1478 }
1479
1480 // �t�@�C��������������
1481 memset(&key, 0, sizeof(key));
1482 begin_read_host_files(pvar, 0);
1483 do {
1484 int host_index = 0;
1485 int matched = 0;
1486 int keybits = 0;
1487 char FAR *data;
1488 int do_write = 0;
1489 length = amount_written = 0;
1490
1491 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1492 break;
1493 }
1494
1495 if (data_index == pvar->hosts_state.file_data_index) {
1496 // index ���i������ == ��������������
1497 break;
1498 }
1499
1500 data = pvar->hosts_state.file_data + data_index;
1501 host_index = eat_spaces(data);
1502
1503 if (data[host_index] == '#') {
1504 do_write = 1;
1505 }
1506 else {
1507 // �z�X�g������
1508 host_index--;
1509 do {
1510 int negated;
1511 int bracketed;
1512 char *end_bracket;
1513 int host_matched = 0;
1514 unsigned short keyfile_port = 22;
1515
1516 host_index++;
1517 negated = data[host_index] == '!';
1518
1519 if (negated) {
1520 host_index++;
1521 bracketed = data[host_index] == '[';
1522 if (bracketed) {
1523 end_bracket = strstr(data + host_index + 1, "]:");
1524 if (end_bracket != NULL) {
1525 *end_bracket = ' ';
1526 host_index++;
1527 }
1528 }
1529 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1530 if (bracketed && end_bracket != NULL) {
1531 *end_bracket = ']';
1532 keyfile_port = atoi(end_bracket + 2);
1533 }
1534 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1535 matched = 0;
1536 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1537 host_index--;
1538 do {
1539 host_index++;
1540 host_index += eat_to_end_of_pattern(data + host_index);
1541 } while (data[host_index] == ',');
1542 break;
1543 }
1544 }
1545 else {
1546 bracketed = data[host_index] == '[';
1547 if (bracketed) {
1548 end_bracket = strstr(data + host_index + 1, "]:");
1549 if (end_bracket != NULL) {
1550 *end_bracket = ' ';
1551 host_index++;
1552 }
1553 }
1554 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1555 if (bracketed && end_bracket != NULL) {
1556 *end_bracket = ']';
1557 keyfile_port = atoi(end_bracket + 2);
1558 }
1559 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1560 matched = 1;
1561 }
1562 }
1563 host_index += eat_to_end_of_pattern(data + host_index);
1564 } while (data[host_index] == ',');
1565
1566 // �z�X�g������������
1567 if (!matched) {
1568 do_write = 1;
1569 }
1570 // �z�X�g��������
1571 else {
1572 // �����`�������� or ���v�����L�[
1573 if (HOSTS_compare_public_key(&pvar->hosts_state.hostkey, &key) != 0) {
1574 do_write = 1;
1575 }
1576 // �����`�������������v�������L�[���X�L�b�v������
1577 }
1578 }
1579
1580 // ������������
1581 if (do_write) {
1582 length = pvar->hosts_state.file_data_index - data_index;
1583 amount_written =
1584 _write(fd, pvar->hosts_state.file_data + data_index,
1585 length);
1586
1587 if (amount_written != length) {
1588 goto error1;
1589 }
1590 }
1591 data_index = pvar->hosts_state.file_data_index;
1592 } while (1); // ������������
1593
1594 error1:
1595 close_result = _close(fd);
1596 if (amount_written != length || close_result == -1) {
1597 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1598 "An error occurred while trying to write the host key.\n"
1599 "The host key could not be written.");
1600 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1601 goto error2;
1602 }
1603
1604 // �������������t�@�C���������l�[��
1605 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1606 _unlink(buf);
1607 rename(filename, buf);
1608
1609 error2:
1610 _unlink(filename);
1611
1612 finish_read_host_files(pvar, 0);
1613
1614 // ���������������������������B
1615 key_init(&key);
1616 }
1617 }
1618
1619
1620 void HOSTS_delete_all_hostkeys(PTInstVar pvar)
1621 {
1622 char FAR *name = pvar->hosts_state.file_names[0];
1623 char *hostname;
1624 unsigned short tcpport;
1625
1626 hostname = pvar->ssh_state.hostname;
1627 tcpport = pvar->ssh_state.tcpport;
1628
1629 if (name == NULL || name[0] == 0) {
1630 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1631 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1632 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1633 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1634 }
1635 else {
1636 Key key; // known_hosts���o�^������������
1637 int length;
1638 char filename[MAX_PATH];
1639 char tmp[L_tmpnam];
1640 int fd;
1641 int amount_written = 0;
1642 int close_result;
1643 int data_index = 0;
1644 char buf[FILENAME_MAX];
1645
1646 // �������������t�@�C�����J��
1647 _getcwd(filename, sizeof(filename));
1648 tmpnam_s(tmp, sizeof(tmp));
1649 strcat_s(filename, sizeof(filename), tmp);
1650 fd = _open(filename,
1651 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1652 _S_IREAD | _S_IWRITE);
1653
1654 if (fd == -1) {
1655 if (errno == EACCES) {
1656 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1657 "An error occurred while trying to write the host key.\n"
1658 "You do not have permission to write to the known-hosts file.");
1659 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1660 }
1661 else {
1662 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1663 "An error occurred while trying to write the host key.\n"
1664 "The host key could not be written.");
1665 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1666 }
1667 return;
1668 }
1669
1670 // �t�@�C��������������
1671 memset(&key, 0, sizeof(key));
1672 begin_read_host_files(pvar, 0);
1673 do {
1674 int host_index = 0;
1675 int matched = 0;
1676 int keybits = 0;
1677 char FAR *data;
1678 int do_write = 0;
1679 length = amount_written = 0;
1680
1681 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) {
1682 break;
1683 }
1684
1685 if (data_index == pvar->hosts_state.file_data_index) {
1686 // index ���i������ == ��������������
1687 break;
1688 }
1689
1690 data = pvar->hosts_state.file_data + data_index;
1691 host_index = eat_spaces(data);
1692
1693 if (data[host_index] == '#') {
1694 do_write = 1;
1695 }
1696 else {
1697 // �z�X�g������
1698 host_index--;
1699 do {
1700 int negated;
1701 int bracketed;
1702 char *end_bracket;
1703 int host_matched = 0;
1704 unsigned short keyfile_port = 22;
1705
1706 host_index++;
1707 negated = data[host_index] == '!';
1708
1709 if (negated) {
1710 host_index++;
1711 bracketed = data[host_index] == '[';
1712 if (bracketed) {
1713 end_bracket = strstr(data + host_index + 1, "]:");
1714 if (end_bracket != NULL) {
1715 *end_bracket = ' ';
1716 host_index++;
1717 }
1718 }
1719 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1720 if (bracketed && end_bracket != NULL) {
1721 *end_bracket = ']';
1722 keyfile_port = atoi(end_bracket + 2);
1723 }
1724 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1725 matched = 0;
1726 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1727 host_index--;
1728 do {
1729 host_index++;
1730 host_index += eat_to_end_of_pattern(data + host_index);
1731 } while (data[host_index] == ',');
1732 break;
1733 }
1734 }
1735 else {
1736 bracketed = data[host_index] == '[';
1737 if (bracketed) {
1738 end_bracket = strstr(data + host_index + 1, "]:");
1739 if (end_bracket != NULL) {
1740 *end_bracket = ' ';
1741 host_index++;
1742 }
1743 }
1744 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1745 if (bracketed && end_bracket != NULL) {
1746 *end_bracket = ']';
1747 keyfile_port = atoi(end_bracket + 2);
1748 }
1749 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1750 matched = 1;
1751 }
1752 }
1753 host_index += eat_to_end_of_pattern(data + host_index);
1754 } while (data[host_index] == ',');
1755
1756 // �z�X�g������������
1757 if (!matched) {
1758 do_write = 1;
1759 }
1760 // �z�X�g��������
1761 else {
1762 // ���������������������B
1763
1764 }
1765 }
1766
1767 // ������������
1768 if (do_write) {
1769 length = pvar->hosts_state.file_data_index - data_index;
1770 amount_written =
1771 _write(fd, pvar->hosts_state.file_data + data_index,
1772 length);
1773
1774 if (amount_written != length) {
1775 goto error1;
1776 }
1777 }
1778 data_index = pvar->hosts_state.file_data_index;
1779 } while (1); // ������������
1780
1781 error1:
1782 close_result = _close(fd);
1783 if (amount_written != length || close_result == -1) {
1784 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1785 "An error occurred while trying to write the host key.\n"
1786 "The host key could not be written.");
1787 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1788 goto error2;
1789 }
1790
1791 // �������������t�@�C���������l�[��
1792 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1793 _unlink(buf);
1794 rename(filename, buf);
1795
1796 error2:
1797 _unlink(filename);
1798
1799 finish_read_host_files(pvar, 0);
1800
1801 // ���������������������������B
1802 key_init(&key);
1803 }
1804 }
1805
1806
1807 //
1808 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1809 // ���[�U���m�F�������B
1810 // TODO: finger print���\�����s���B
1811 // (2006.3.25 yutaka)
1812 //
1813 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1814 LPARAM lParam)
1815 {
1816 PTInstVar pvar;
1817 LOGFONT logfont;
1818 HFONT font;
1819 char uimsg[MAX_UIMSG];
1820
1821 switch (msg) {
1822 case WM_INITDIALOG:
1823 pvar = (PTInstVar) lParam;
1824 pvar->hosts_state.hosts_dialog = dlg;
1825 SetWindowLong(dlg, DWL_USER, lParam);
1826
1827 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1828 GetWindowText(dlg, uimsg, sizeof(uimsg));
1829 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1830 SetWindowText(dlg, pvar->ts->UIMsg);
1831 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1832 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING", pvar, uimsg);
1833 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1834 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1835 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING2", pvar, uimsg);
1836 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1837 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1838 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1839 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1840 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
1841 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FP_HASH_ALGORITHM", pvar, uimsg);
1842 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
1843 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1844 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1845 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1846 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1847 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1848 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1849 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1850 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1851 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1852
1853 switch (pvar->dns_key_check) {
1854 case DNS_VERIFY_NOTFOUND:
1855 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1856 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1857 break;
1858 case DNS_VERIFY_MATCH:
1859 case DNS_VERIFY_AUTH_MATCH:
1860 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1861 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1862 break;
1863 case DNS_VERIFY_MISMATCH:
1864 case DNS_VERIFY_AUTH_MISMATCH:
1865 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1866 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1867 break;
1868 case DNS_VERIFY_DIFFERENTTYPE:
1869 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1870 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1871 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1872 break;
1873 }
1874
1875 switch (pvar->dns_key_check) {
1876 case DNS_VERIFY_MATCH:
1877 case DNS_VERIFY_MISMATCH:
1878 case DNS_VERIFY_DIFFERENTTYPE:
1879 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1880 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1881 break;
1882 case DNS_VERIFY_AUTH_MATCH:
1883 case DNS_VERIFY_AUTH_MISMATCH:
1884 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1885 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1886 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1887 break;
1888 }
1889
1890 init_hosts_dlg(pvar, dlg);
1891
1892 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1893 GetObject(font, sizeof(LOGFONT), &logfont);
1894 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1895 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1896 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1897 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1898 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1899 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1900 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1901 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1902 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1903 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
1904 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1905 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1906 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1907 }
1908 else {
1909 DlgHostsAddFont = NULL;
1910 }
1911
1912 // add host check box���`�F�b�N���f�t�H���g������������
1913 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1914
1915 return TRUE; /* because we do not set the focus */
1916
1917 case WM_COMMAND:
1918 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1919
1920 switch (LOWORD(wParam)) {
1921 case IDC_CONTINUE:
1922 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
1923 if (!pvar->cv->Ready) {
1924 goto canceled;
1925 }
1926
1927 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1928 add_host_key(pvar);
1929 }
1930
1931 if (SSHv1(pvar)) {
1932 SSH_notify_host_OK(pvar);
1933 } else { // SSH2
1934 // SSH2���������� SSH_notify_host_OK() �������B
1935 }
1936
1937 pvar->hosts_state.hosts_dialog = NULL;
1938
1939 EndDialog(dlg, 1);
1940
1941 if (DlgHostsAddFont != NULL) {
1942 DeleteObject(DlgHostsAddFont);
1943 }
1944
1945 return TRUE;
1946
1947 case IDCANCEL: /* kill the connection */
1948 canceled:
1949 pvar->hosts_state.hosts_dialog = NULL;
1950 notify_closed_connection(pvar, "authentication cancelled");
1951 EndDialog(dlg, 0);
1952
1953 if (DlgHostsAddFont != NULL) {
1954 DeleteObject(DlgHostsAddFont);
1955 }
1956
1957 return TRUE;
1958
1959 case IDC_FP_HASH_ALG_MD5:
1960 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
1961 return TRUE;
1962
1963 case IDC_FP_HASH_ALG_SHA256:
1964 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
1965 return TRUE;
1966
1967 default:
1968 return FALSE;
1969 }
1970
1971 default:
1972 return FALSE;
1973 }
1974 }
1975
1976 //
1977 // �u�����������m�F�_�C�A���O������
1978 //
1979 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1980 LPARAM lParam)
1981 {
1982 PTInstVar pvar;
1983 LOGFONT logfont;
1984 HFONT font;
1985 char uimsg[MAX_UIMSG];
1986
1987 switch (msg) {
1988 case WM_INITDIALOG:
1989 pvar = (PTInstVar) lParam;
1990 pvar->hosts_state.hosts_dialog = dlg;
1991 SetWindowLong(dlg, DWL_USER, lParam);
1992
1993 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1995 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
1996 SetWindowText(dlg, pvar->ts->UIMsg);
1997 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1998 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
1999 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2000 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2001 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
2002 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2003 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2004 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
2005 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2006 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2007 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FP_HASH_ALGORITHM", pvar, uimsg);
2008 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2009 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2010 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
2011 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2012 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2013 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2014 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2015 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2016 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2017 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2018
2019 switch (pvar->dns_key_check) {
2020 case DNS_VERIFY_NOTFOUND:
2021 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2022 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2023 break;
2024 case DNS_VERIFY_MATCH:
2025 case DNS_VERIFY_AUTH_MATCH:
2026 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2027 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2028 break;
2029 case DNS_VERIFY_MISMATCH:
2030 case DNS_VERIFY_AUTH_MISMATCH:
2031 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2032 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2033 break;
2034 case DNS_VERIFY_DIFFERENTTYPE:
2035 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2036 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2037 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2038 break;
2039 }
2040
2041 switch (pvar->dns_key_check) {
2042 case DNS_VERIFY_MATCH:
2043 case DNS_VERIFY_MISMATCH:
2044 case DNS_VERIFY_DIFFERENTTYPE:
2045 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2046 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2047 break;
2048 case DNS_VERIFY_AUTH_MATCH:
2049 case DNS_VERIFY_AUTH_MISMATCH:
2050 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2051 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2052 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2053 break;
2054 }
2055
2056 init_hosts_dlg(pvar, dlg);
2057
2058 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2059 GetObject(font, sizeof(LOGFONT), &logfont);
2060 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
2061 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2062 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2063 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2064 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2065 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2066 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2067 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2068 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2069 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2070 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2071 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2072 }
2073 else {
2074 DlgHostsReplaceFont = NULL;
2075 }
2076
2077 // �f�t�H���g���`�F�b�N����������
2078 return TRUE; /* because we do not set the focus */
2079
2080 case WM_COMMAND:
2081 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2082
2083 switch (LOWORD(wParam)) {
2084 case IDC_CONTINUE:
2085 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2086 if (!pvar->cv->Ready) {
2087 goto canceled;
2088 }
2089
2090 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2091 add_host_key(pvar);
2092 delete_different_key(pvar);
2093 }
2094
2095 if (SSHv1(pvar)) {
2096 SSH_notify_host_OK(pvar);
2097 } else { // SSH2
2098 // SSH2���������� SSH_notify_host_OK() �������B
2099 }
2100
2101 pvar->hosts_state.hosts_dialog = NULL;
2102
2103 EndDialog(dlg, 1);
2104
2105 if (DlgHostsReplaceFont != NULL) {
2106 DeleteObject(DlgHostsReplaceFont);
2107 }
2108
2109 return TRUE;
2110
2111 case IDCANCEL: /* kill the connection */
2112 canceled:
2113 pvar->hosts_state.hosts_dialog = NULL;
2114 notify_closed_connection(pvar, "authentication cancelled");
2115 EndDialog(dlg, 0);
2116
2117 if (DlgHostsReplaceFont != NULL) {
2118 DeleteObject(DlgHostsReplaceFont);
2119 }
2120
2121 return TRUE;
2122
2123 case IDC_FP_HASH_ALG_MD5:
2124 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2125 return TRUE;
2126
2127 case IDC_FP_HASH_ALG_SHA256:
2128 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2129 return TRUE;
2130
2131 default:
2132 return FALSE;
2133 }
2134
2135 default:
2136 return FALSE;
2137 }
2138 }
2139
2140 //
2141 // �����z�X�g�����`�����������������m�F�_�C�A���O������
2142 //
2143 static BOOL CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2144 LPARAM lParam)
2145 {
2146 PTInstVar pvar;
2147 LOGFONT logfont;
2148 HFONT font;
2149 char uimsg[MAX_UIMSG];
2150
2151 switch (msg) {
2152 case WM_INITDIALOG:
2153 pvar = (PTInstVar) lParam;
2154 pvar->hosts_state.hosts_dialog = dlg;
2155 SetWindowLong(dlg, DWL_USER, lParam);
2156
2157 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2158 GetWindowText(dlg, uimsg, sizeof(uimsg));
2159 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
2160 SetWindowText(dlg, pvar->ts->UIMsg);
2161 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
2162 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
2163 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2164 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2165 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
2166 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2167 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2168 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
2169 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2170 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2171 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FP_HASH_ALGORITHM", pvar, uimsg);
2172 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2173 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2174 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
2175 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2176 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2177 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2178 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2179 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2180 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2181 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2182
2183 switch (pvar->dns_key_check) {
2184 case DNS_VERIFY_NOTFOUND:
2185 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2186 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2187 break;
2188 case DNS_VERIFY_MATCH:
2189 case DNS_VERIFY_AUTH_MATCH:
2190 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2191 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2192 break;
2193 case DNS_VERIFY_MISMATCH:
2194 case DNS_VERIFY_AUTH_MISMATCH:
2195 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2196 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2197 break;
2198 case DNS_VERIFY_DIFFERENTTYPE:
2199 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2200 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2201 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2202 break;
2203 }
2204
2205 switch (pvar->dns_key_check) {
2206 case DNS_VERIFY_MATCH:
2207 case DNS_VERIFY_MISMATCH:
2208 case DNS_VERIFY_DIFFERENTTYPE:
2209 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2210 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2211 break;
2212 case DNS_VERIFY_AUTH_MATCH:
2213 case DNS_VERIFY_AUTH_MISMATCH:
2214 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2215 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2216 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2217 break;
2218 }
2219
2220 init_hosts_dlg(pvar, dlg);
2221
2222 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2223 GetObject(font, sizeof(LOGFONT), &logfont);
2224 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
2225 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2226 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2227 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2228 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2229 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2230 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2231 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2232 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2233 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2234 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2235 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2236 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2237 }
2238 else {
2239 DlgHostsAddFont = NULL;
2240 }
2241
2242 // add host check box ���f�t�H���g�� off ������
2243 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
2244
2245 return TRUE; /* because we do not set the focus */
2246
2247 case WM_COMMAND:
2248 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2249
2250 switch (LOWORD(wParam)) {
2251 case IDC_CONTINUE:
2252 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2253 if (!pvar->cv->Ready) {
2254 goto canceled;
2255 }
2256
2257 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2258 add_host_key(pvar);
2259 }
2260
2261 if (SSHv1(pvar)) {
2262 SSH_notify_host_OK(pvar);
2263 } else { // SSH2
2264 // SSH2���������� SSH_notify_host_OK() �������B
2265 }
2266
2267 pvar->hosts_state.hosts_dialog = NULL;
2268
2269 EndDialog(dlg, 1);
2270
2271 if (DlgHostsAddFont != NULL) {
2272 DeleteObject(DlgHostsAddFont);
2273 }
2274
2275 return TRUE;
2276
2277 case IDCANCEL: /* kill the connection */
2278 canceled:
2279 pvar->hosts_state.hosts_dialog = NULL;
2280 notify_closed_connection(pvar, "authentication cancelled");
2281 EndDialog(dlg, 0);
2282
2283 if (DlgHostsAddFont != NULL) {
2284 DeleteObject(DlgHostsAddFont);
2285 }
2286
2287 return TRUE;
2288
2289 case IDC_FP_HASH_ALG_MD5:
2290 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2291 return TRUE;
2292
2293 case IDC_FP_HASH_ALG_SHA256:
2294 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2295 return TRUE;
2296
2297 default:
2298 return FALSE;
2299 }
2300
2301 default:
2302 return FALSE;
2303 }
2304 }
2305
2306 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
2307 {
2308 if (pvar->hosts_state.hosts_dialog == NULL) {
2309 HWND cur_active = GetActiveWindow();
2310
2311 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
2312 cur_active != NULL ? cur_active : wnd,
2313 hosts_add_dlg_proc, (LPARAM) pvar);
2314 }
2315 }
2316
2317 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
2318 {
2319 if (pvar->hosts_state.hosts_dialog == NULL) {
2320 HWND cur_active = GetActiveWindow();
2321
2322 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
2323 cur_active != NULL ? cur_active : wnd,
2324 hosts_replace_dlg_proc, (LPARAM) pvar);
2325 }
2326 }
2327
2328 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
2329 {
2330 if (pvar->hosts_state.hosts_dialog == NULL) {
2331 HWND cur_active = GetActiveWindow();
2332
2333 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2334 cur_active != NULL ? cur_active : wnd,
2335 hosts_add2_dlg_proc, (LPARAM) pvar);
2336 }
2337 }
2338
2339 //
2340 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
2341 // key: �T�[�o���������J��
2342 //
2343 // SSH2���������� (2006.3.24 yutaka)
2344 //
2345 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
2346 {
2347 int found_different_key = 0, found_different_type_key = 0;
2348 Key key2; // known_hosts���o�^������������
2349
2350 pvar->dns_key_check = DNS_VERIFY_NONE;
2351
2352 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
2353 if (pvar->hosts_state.prefetched_hostname != NULL
2354 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
2355 && HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key) == 1) {
2356
2357 if (SSHv1(pvar)) {
2358 SSH_notify_host_OK(pvar);
2359 } else {
2360 // SSH2���������� SSH_notify_host_OK() �������B
2361 }
2362 return TRUE;
2363 }
2364
2365 // �������������������������A�������_���t�@�C��������������
2366 memset(&key2, 0, sizeof(key2));
2367 if (begin_read_host_files(pvar, 0)) {
2368 do {
2369 if (!read_host_key(pvar, hostname, tcpport, 0, 0, &key2)) {
2370 break;
2371 }
2372
2373 if (key2.type != KEY_UNSPEC) {
2374 int match = HOSTS_compare_public_key(&key2, key);
2375 if (match == 1) {
2376 finish_read_host_files(pvar, 0);
2377 // ���������G���g�����Q�������A���v�����L�[�������������������B
2378 // SSH2���������������������������B(2006.3.29 yutaka)
2379 if (SSHv1(pvar)) {
2380 SSH_notify_host_OK(pvar);
2381 } else {
2382 // SSH2���������� SSH_notify_host_OK() �������B
2383 }
2384 return TRUE;
2385 }
2386 else if (match == 0) {
2387 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2388 found_different_key = 1;
2389 }
2390 else {
2391 // �L�[���`������������
2392 found_different_type_key = 1;
2393 }
2394 }
2395 } while (key2.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2396
2397 key_init(&key2);
2398 finish_read_host_files(pvar, 0);
2399 }
2400
2401 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2402 key_copy(&pvar->hosts_state.hostkey, key);
2403
2404 free(pvar->hosts_state.prefetched_hostname);
2405 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2406
2407 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2408 if (pvar->nocheck_known_hosts == TRUE) {
2409 return TRUE;
2410 }
2411
2412 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2413 pvar->dns_key_check = verify_hostkey_dns(pvar, hostname, key);
2414 }
2415
2416 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
2417 // �������K�v�����������A�����R�[�������X�����B
2418 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
2419 // (2007.10.1 yutaka)
2420 if (found_different_key) {
2421 HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar);
2422 }
2423 else if (found_different_type_key) {
2424 HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar);
2425 }
2426 else {
2427 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
2428 }
2429
2430 return TRUE;
2431 }
2432
2433 void HOSTS_notify_disconnecting(PTInstVar pvar)
2434 {
2435 if (pvar->hosts_state.hosts_dialog != NULL) {
2436 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
2437 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
2438 EnableWindow(pvar->NotificationWindow, TRUE);
2439 }
2440 }
2441
2442 void HOSTS_end(PTInstVar pvar)
2443 {
2444 int i;
2445
2446 free(pvar->hosts_state.prefetched_hostname);
2447 key_init(&pvar->hosts_state.hostkey);
2448
2449 if (pvar->hosts_state.file_names != NULL) {
2450 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
2451 free(pvar->hosts_state.file_names[i]);
2452 }
2453 free(pvar->hosts_state.file_names);
2454 }
2455 }

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