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

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