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 4559 - (show annotations) (download) (as text)
Mon Aug 1 07:21:58 2011 UTC (12 years, 8 months ago) by doda
File MIME type: text/x-csrc
File size: 56257 byte(s)
SSHFP 検証の結果を Security Warning ダイアログに表示するようにした。メッセージは暫定。

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
34 #include "ttxssh.h"
35 #include "util.h"
36 #include "resource.h"
37 #include "matcher.h"
38 #include "ssh.h"
39 #include "key.h"
40 #include "hosts.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 #include <windns.h>
55
56 #define DNS_TYPE_SSHFP 44
57 typedef struct {
58 BYTE Algorithm;
59 BYTE DigestType;
60 BYTE Digest[1];
61 } DNS_SSHFP_DATA, *PDNS_SSHFP_DATA;
62 enum verifydns_result {
63 DNS_VERIFY_NONE,
64 DNS_VERIFY_NOTFOUND,
65 DNS_VERIFY_MATCH,
66 DNS_VERIFY_MISMATCH,
67 DNS_VERIFY_DIFFERENTTYPE,
68 DNS_VERIFY_AUTH_MATCH,
69 DNS_VERIFY_AUTH_MISMATCH,
70 DNS_VERIFY_AUTH_DIFFERENTTYPE
71 };
72
73 static HFONT DlgHostsAddFont;
74 static HFONT DlgHostsReplaceFont;
75
76 // BASE64�\���������i��������'='�����������������j
77 static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
78
79
80 // �z�X�g�L�[�������� (2006.3.21 yutaka)
81 static void init_hostkey(Key *key)
82 {
83 key->type = KEY_UNSPEC;
84
85 // SSH1
86 key->bits = 0;
87 if (key->exp != NULL) {
88 free(key->exp);
89 key->exp = NULL;
90 }
91 if (key->mod != NULL) {
92 free(key->mod);
93 key->mod = NULL;
94 }
95
96 // SSH2
97 if (key->dsa != NULL) {
98 DSA_free(key->dsa);
99 key->dsa = NULL;
100 }
101 if (key->rsa != NULL) {
102 RSA_free(key->rsa);
103 key->rsa = NULL;
104 }
105 if (key->ecdsa != NULL) {
106 EC_KEY_free(key->ecdsa);
107 key->ecdsa = NULL;
108 }
109 }
110
111
112 static char FAR *FAR * parse_multi_path(char FAR * buf)
113 {
114 int i;
115 int ch;
116 int num_paths = 1;
117 char FAR *FAR * result;
118 int last_path_index;
119
120 for (i = 0; (ch = buf[i]) != 0; i++) {
121 if (ch == ';') {
122 num_paths++;
123 }
124 }
125
126 result =
127 (char FAR * FAR *) malloc(sizeof(char FAR *) * (num_paths + 1));
128
129 last_path_index = 0;
130 num_paths = 0;
131 for (i = 0; (ch = buf[i]) != 0; i++) {
132 if (ch == ';') {
133 buf[i] = 0;
134 result[num_paths] = _strdup(buf + last_path_index);
135 num_paths++;
136 buf[i] = ch;
137 last_path_index = i + 1;
138 }
139 }
140 if (i > last_path_index) {
141 result[num_paths] = _strdup(buf + last_path_index);
142 num_paths++;
143 }
144 result[num_paths] = NULL;
145 return result;
146 }
147
148 void HOSTS_init(PTInstVar pvar)
149 {
150 pvar->hosts_state.prefetched_hostname = NULL;
151 init_hostkey(&pvar->hosts_state.hostkey);
152 pvar->hosts_state.hosts_dialog = NULL;
153 pvar->hosts_state.file_names = NULL;
154 }
155
156 void HOSTS_open(PTInstVar pvar)
157 {
158 pvar->hosts_state.file_names =
159 parse_multi_path(pvar->session_settings.KnownHostsFiles);
160 }
161
162 //
163 // known_hosts�t�@�C�������e�������� pvar->hosts_state.file_data ����������
164 //
165 static int begin_read_file(PTInstVar pvar, char FAR * name,
166 int suppress_errors)
167 {
168 int fd;
169 int length;
170 int amount_read;
171 char buf[2048];
172
173 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
174 fd = _open(buf, _O_RDONLY | _O_SEQUENTIAL | _O_BINARY);
175 if (fd == -1) {
176 if (!suppress_errors) {
177 if (errno == ENOENT) {
178 UTIL_get_lang_msg("MSG_HOSTS_READ_ENOENT_ERROR", pvar,
179 "An error occurred while trying to read a known_hosts file.\n"
180 "The specified filename does not exist.");
181 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
182 } else {
183 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
184 "An error occurred while trying to read a known_hosts file.");
185 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
186 }
187 }
188 return 0;
189 }
190
191 length = (int) _lseek(fd, 0, SEEK_END);
192 _lseek(fd, 0, SEEK_SET);
193
194 if (length >= 0 && length < 0x7FFFFFFF) {
195 pvar->hosts_state.file_data = malloc(length + 1);
196 if (pvar->hosts_state.file_data == NULL) {
197 if (!suppress_errors) {
198 UTIL_get_lang_msg("MSG_HOSTS_ALLOC_ERROR", pvar,
199 "Memory ran out while trying to allocate space to read a known_hosts file.");
200 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
201 }
202 _close(fd);
203 return 0;
204 }
205 } else {
206 if (!suppress_errors) {
207 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
208 "An error occurred while trying to read a known_hosts file.");
209 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
210 }
211 _close(fd);
212 return 0;
213 }
214
215 amount_read = _read(fd, pvar->hosts_state.file_data, length);
216 pvar->hosts_state.file_data[length] = 0;
217
218 _close(fd);
219
220 if (amount_read != length) {
221 if (!suppress_errors) {
222 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
223 "An error occurred while trying to read a known_hosts file.");
224 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
225 }
226 free(pvar->hosts_state.file_data);
227 pvar->hosts_state.file_data = NULL;
228 return 0;
229 } else {
230 return 1;
231 }
232 }
233
234 static int end_read_file(PTInstVar pvar, int suppress_errors)
235 {
236 free(pvar->hosts_state.file_data);
237 pvar->hosts_state.file_data = NULL;
238 return 1;
239 }
240
241 static int begin_read_host_files(PTInstVar pvar, int suppress_errors)
242 {
243 pvar->hosts_state.file_num = 0;
244 pvar->hosts_state.file_data = NULL;
245 return 1;
246 }
247
248 // MIME64�����������X�L�b�v����
249 static int eat_base64(char FAR * data)
250 {
251 int index = 0;
252 int ch;
253
254 for (;;) {
255 ch = data[index];
256 if (ch == '=' || strchr(base64, ch)) {
257 // BASE64���\�������������������� index ���i����
258 index++;
259 } else {
260 break;
261 }
262 }
263
264 return index;
265 }
266
267 static int eat_spaces(char FAR * data)
268 {
269 int index = 0;
270 int ch;
271
272 while ((ch = data[index]) == ' ' || ch == '\t') {
273 index++;
274 }
275 return index;
276 }
277
278 static int eat_digits(char FAR * data)
279 {
280 int index = 0;
281 int ch;
282
283 while ((ch = data[index]) >= '0' && ch <= '9') {
284 index++;
285 }
286 return index;
287 }
288
289 static int eat_to_end_of_line(char FAR * data)
290 {
291 int index = 0;
292 int ch;
293
294 while ((ch = data[index]) != '\n' && ch != '\r' && ch != 0) {
295 index++;
296 }
297
298 while ((ch = data[index]) == '\n' || ch == '\r') {
299 index++;
300 }
301
302 return index;
303 }
304
305 static int eat_to_end_of_pattern(char FAR * data)
306 {
307 int index = 0;
308 int ch;
309
310 while (ch = data[index], is_pattern_char(ch)) {
311 index++;
312 }
313
314 return index;
315 }
316
317 //
318 // BASE64�f�R�[�h�������s���B(rfc1521)
319 // src�o�b�t�@�� null-terminate ���������K�v�����B
320 //
321 static int uudecode(unsigned char *src, int srclen, unsigned char *target, int targsize)
322 {
323 char pad = '=';
324 int tarindex, state, ch;
325 char *pos;
326
327 state = 0;
328 tarindex = 0;
329
330 while ((ch = *src++) != '\0') {
331 if (isspace(ch)) /* Skip whitespace anywhere. */
332 continue;
333
334 if (ch == pad)
335 break;
336
337 pos = strchr(base64, ch);
338 if (pos == 0) /* A non-base64 character. */
339 return (-1);
340
341 switch (state) {
342 case 0:
343 if (target) {
344 if (tarindex >= targsize)
345 return (-1);
346 target[tarindex] = (pos - base64) << 2;
347 }
348 state = 1;
349 break;
350 case 1:
351 if (target) {
352 if (tarindex + 1 >= targsize)
353 return (-1);
354 target[tarindex] |= (pos - base64) >> 4;
355 target[tarindex+1] = ((pos - base64) & 0x0f) << 4 ;
356 }
357 tarindex++;
358 state = 2;
359 break;
360 case 2:
361 if (target) {
362 if (tarindex + 1 >= targsize)
363 return (-1);
364 target[tarindex] |= (pos - base64) >> 2;
365 target[tarindex+1] = ((pos - base64) & 0x03) << 6;
366 }
367 tarindex++;
368 state = 3;
369 break;
370 case 3:
371 if (target) {
372 if (tarindex >= targsize)
373 return (-1);
374 target[tarindex] |= (pos - base64);
375 }
376 tarindex++;
377 state = 0;
378 break;
379 }
380 }
381
382 /*
383 * We are done decoding Base-64 chars. Let's see if we ended
384 * on a byte boundary, and/or with erroneous trailing characters.
385 */
386
387 if (ch == pad) { /* We got a pad char. */
388 ch = *src++; /* Skip it, get next. */
389 switch (state) {
390 case 0: /* Invalid = in first position */
391 case 1: /* Invalid = in second position */
392 return (-1);
393
394 case 2: /* Valid, means one byte of info */
395 /* Skip any number of spaces. */
396 for (; ch != '\0'; ch = *src++)
397 if (!isspace(ch))
398 break;
399 /* Make sure there is another trailing = sign. */
400 if (ch != pad)
401 return (-1);
402 ch = *src++; /* Skip the = */
403 /* Fall through to "single trailing =" case. */
404 /* FALLTHROUGH */
405
406 case 3: /* Valid, means two bytes of info */
407 /*
408 * We know this char is an =. Is there anything but
409 * whitespace after it?
410 */
411 for (; ch != '\0'; ch = *src++)
412 if (!isspace(ch))
413 return (-1);
414
415 /*
416 * Now make sure for cases 2 and 3 that the "extra"
417 * bits that slopped past the last full byte were
418 * zeros. If we don't check them, they become a
419 * subliminal channel.
420 */
421 if (target && target[tarindex] != 0)
422 return (-1);
423 }
424 } else {
425 /*
426 * We ended by seeing the end of the string. Make sure we
427 * have no partial bytes lying around.
428 */
429 if (state != 0)
430 return (-1);
431 }
432
433 return (tarindex);
434 }
435
436
437 // SSH2���� BASE64 �`�����i�[����������
438 static Key *parse_uudecode(char *data)
439 {
440 int count;
441 unsigned char *blob = NULL;
442 int len, n;
443 Key *key = NULL;
444 char ch;
445
446 // BASE64���������T�C�Y������
447 count = eat_base64(data);
448 len = 2 * count;
449 blob = malloc(len);
450 if (blob == NULL)
451 goto error;
452
453 // BASE64�f�R�[�h
454 ch = data[count];
455 data[count] = '\0'; // ���������s�R�[�h������������������������������������
456 n = uudecode(data, count, blob, len);
457 data[count] = ch;
458 if (n < 0) {
459 goto error;
460 }
461
462 key = key_from_blob(blob, n);
463 if (key == NULL)
464 goto error;
465
466 error:
467 if (blob != NULL)
468 free(blob);
469
470 return (key);
471 }
472
473
474 static char FAR *parse_bignum(char FAR * data)
475 {
476 uint32 digits = 0;
477 BIGNUM *num = BN_new();
478 BIGNUM *billion = BN_new();
479 BIGNUM *digits_num = BN_new();
480 BN_CTX *ctx = BN_CTX_new();
481 char FAR *result;
482 int ch;
483 int leftover_digits = 1;
484
485 BN_CTX_init(ctx);
486 BN_set_word(num, 0);
487 BN_set_word(billion, 1000000000L);
488
489 while ((ch = *data) >= '0' && ch <= '9') {
490 if (leftover_digits == 1000000000L) {
491 BN_set_word(digits_num, digits);
492 BN_mul(num, num, billion, ctx);
493 BN_add(num, num, digits_num);
494 leftover_digits = 1;
495 digits = 0;
496 }
497
498 digits = digits * 10 + ch - '0';
499 leftover_digits *= 10;
500 data++;
501 }
502
503 BN_set_word(digits_num, digits);
504 BN_set_word(billion, leftover_digits);
505 BN_mul(num, num, billion, ctx);
506 BN_add(num, num, digits_num);
507
508 result = (char FAR *) malloc(2 + BN_num_bytes(num));
509 set_ushort16_MSBfirst(result, BN_num_bits(num));
510 BN_bn2bin(num, result + 2);
511
512 BN_CTX_free(ctx);
513 BN_free(digits_num);
514 BN_free(num);
515 BN_free(billion);
516
517 return result;
518 }
519
520 //
521 // known_hosts�t�@�C�������e���������A�w�������z�X�g�����J�����T���B
522 //
523 static int check_host_key(PTInstVar pvar, char FAR * hostname,
524 unsigned short tcpport, char FAR * data)
525 {
526 int index = eat_spaces(data);
527 int matched = 0;
528 int keybits = 0;
529
530 if (data[index] == '#') {
531 return index + eat_to_end_of_line(data + index);
532 }
533
534 /* if we find an empty line, then it won't have any patterns matching the hostname
535 and so we skip it */
536 index--;
537 do {
538 int negated;
539 int bracketed;
540 char *end_bracket;
541 int host_matched = 0;
542 unsigned short keyfile_port = 22;
543
544 index++;
545 negated = data[index] == '!';
546
547 if (negated) {
548 index++;
549 bracketed = data[index] == '[';
550 if (bracketed) {
551 end_bracket = strstr(data + index + 1, "]:");
552 if (end_bracket != NULL) {
553 *end_bracket = ' ';
554 index++;
555 }
556 }
557 host_matched = match_pattern(data + index, hostname);
558 if (bracketed && end_bracket != NULL) {
559 *end_bracket = ']';
560 keyfile_port = atoi(end_bracket + 2);
561 }
562 if (host_matched && keyfile_port == tcpport) {
563 return index + eat_to_end_of_line(data + index);
564 }
565 } else {
566 bracketed = data[index] == '[';
567 if (bracketed) {
568 end_bracket = strstr(data + index + 1, "]:");
569 if (end_bracket != NULL) {
570 *end_bracket = ' ';
571 index++;
572 }
573 }
574 host_matched = match_pattern(data + index, hostname);
575 if (bracketed && end_bracket != NULL) {
576 *end_bracket = ']';
577 keyfile_port = atoi(end_bracket + 2);
578 }
579 if (host_matched && keyfile_port == tcpport) {
580 matched = 1;
581 }
582 }
583
584 index += eat_to_end_of_pattern(data + index);
585 } while (data[index] == ',');
586
587 if (!matched) {
588 return index + eat_to_end_of_line(data + index);
589 } else {
590 // ���������������t�H�[�}�b�g��������
591 // �����A���������v�����G���g�����������������������B
592 /*
593 [SSH1]
594 192.168.1.2 1024 35 13032....
595
596 [SSH2]
597 192.168.1.2 ssh-rsa AAAAB3NzaC1....
598 192.168.1.2 ssh-dss AAAAB3NzaC1....
599 192.168.1.2 rsa AAAAB3NzaC1....
600 192.168.1.2 dsa AAAAB3NzaC1....
601 192.168.1.2 rsa1 AAAAB3NzaC1....
602 */
603 int rsa1_key_bits;
604
605 index += eat_spaces(data + index);
606
607 rsa1_key_bits = atoi(data + index);
608 if (rsa1_key_bits > 0) { // RSA1������
609 if (!SSHv1(pvar)) { // SSH2��������������������
610 return index + eat_to_end_of_line(data + index);
611 }
612
613 pvar->hosts_state.hostkey.type = KEY_RSA1;
614
615 pvar->hosts_state.hostkey.bits = rsa1_key_bits;
616 index += eat_digits(data + index);
617 index += eat_spaces(data + index);
618
619 pvar->hosts_state.hostkey.exp = parse_bignum(data + index);
620 index += eat_digits(data + index);
621 index += eat_spaces(data + index);
622
623 pvar->hosts_state.hostkey.mod = parse_bignum(data + index);
624
625 /*
626 if (pvar->hosts_state.key_bits < 0
627 || pvar->hosts_state.key_exp == NULL
628 || pvar->hosts_state.key_mod == NULL) {
629 pvar->hosts_state.key_bits = 0;
630 free(pvar->hosts_state.key_exp);
631 free(pvar->hosts_state.key_mod);
632 }*/
633
634 } else {
635 char *cp, *p;
636 Key *key;
637
638 if (!SSHv2(pvar)) { // SSH1��������������������
639 return index + eat_to_end_of_line(data + index);
640 }
641
642 cp = data + index;
643 p = strchr(cp, ' ');
644 if (p == NULL) {
645 return index + eat_to_end_of_line(data + index);
646 }
647 index += (p - cp); // setup index
648 *p = '\0';
649 pvar->hosts_state.hostkey.type = get_keytype_from_name(cp);
650 *p = ' ';
651
652 index += eat_spaces(data + index); // update index
653
654 // uudecode
655 key = parse_uudecode(data + index);
656 if (key == NULL) {
657 return index + eat_to_end_of_line(data + index);
658 }
659
660 // setup
661 pvar->hosts_state.hostkey.type = key->type;
662 pvar->hosts_state.hostkey.dsa = key->dsa;
663 pvar->hosts_state.hostkey.rsa = key->rsa;
664 pvar->hosts_state.hostkey.ecdsa = key->ecdsa;
665
666 index += eat_base64(data + index);
667 index += eat_spaces(data + index);
668
669 // Key�\�������g���������� (2008.3.2 yutaka)
670 free(key);
671 }
672
673 return index + eat_to_end_of_line(data + index);
674 }
675 }
676
677 //
678 // known_hosts�t�@�C�������z�X�g�������v�����s������
679 //
680 static int read_host_key(PTInstVar pvar,
681 char FAR * hostname, unsigned short tcpport,
682 int suppress_errors, int return_always)
683 {
684 int i;
685 int while_flg;
686
687 for (i = 0; hostname[i] != 0; i++) {
688 int ch = hostname[i];
689
690 if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
691 if (!suppress_errors) {
692 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
693 "The host name contains an invalid character.\n"
694 "This session will be terminated.");
695 notify_fatal_error(pvar, pvar->ts->UIMsg);
696 }
697 return 0;
698 }
699 }
700
701 if (i == 0) {
702 if (!suppress_errors) {
703 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
704 "The host name should not be empty.\n"
705 "This session will be terminated.");
706 notify_fatal_error(pvar, pvar->ts->UIMsg);
707 }
708 return 0;
709 }
710
711 // hostkey type is KEY_UNSPEC.
712 init_hostkey(&pvar->hosts_state.hostkey);
713
714 do {
715 if (pvar->hosts_state.file_data == NULL
716 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
717 char FAR *filename;
718 int keep_going = 1;
719
720 if (pvar->hosts_state.file_data != NULL) {
721 end_read_file(pvar, suppress_errors);
722 }
723
724 do {
725 filename =
726 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
727
728 if (filename == NULL) {
729 return 1;
730 } else {
731 pvar->hosts_state.file_num++;
732
733 if (filename[0] != 0) {
734 if (begin_read_file(pvar, filename, suppress_errors)) {
735 pvar->hosts_state.file_data_index = 0;
736 keep_going = 0;
737 }
738 }
739 }
740 } while (keep_going);
741 }
742
743 pvar->hosts_state.file_data_index +=
744 check_host_key(pvar, hostname, tcpport,
745 pvar->hosts_state.file_data +
746 pvar->hosts_state.file_data_index);
747
748 if (!return_always) {
749 // �L�����L�[��������������
750 while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
751 }
752 else {
753 while_flg = 0;
754 }
755 } while (while_flg);
756
757 return 1;
758 }
759
760 static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
761 {
762 if (pvar->hosts_state.file_data != NULL) {
763 end_read_file(pvar, suppress_errors);
764 }
765 }
766
767 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
768 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport)
769 {
770 if (!begin_read_host_files(pvar, 1)) {
771 return;
772 }
773
774 if (!read_host_key(pvar, hostname, tcpport, 1, 0)) {
775 return;
776 }
777
778 free(pvar->hosts_state.prefetched_hostname);
779 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
780
781 finish_read_host_files(pvar, 1);
782 }
783
784 static BOOL equal_mp_ints(unsigned char FAR * num1,
785 unsigned char FAR * num2)
786 {
787 if (num1 == NULL || num2 == NULL) {
788 return FALSE;
789 } else {
790 uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
791
792 if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
793 return FALSE; /* different byte lengths */
794 } else {
795 return memcmp(num1 + 2, num2 + 2, bytes) == 0;
796 }
797 }
798 }
799
800 // ���J����������������������
801 // -1 ... �����^������
802 // 0 ... ����������
803 // 1 ... ������
804 static int match_key(PTInstVar pvar, Key *key)
805 {
806 int bits;
807 unsigned char FAR * exp;
808 unsigned char FAR * mod;
809 const EC_GROUP *group;
810 const EC_POINT *pa, *pb;
811
812 if (pvar->hosts_state.hostkey.type != key->type) {
813 return -1;
814 }
815
816 switch (key->type) {
817 case KEY_RSA1: // SSH1 host public key
818 bits = key->bits;
819 exp = key->exp;
820 mod = key->mod;
821
822 /* just check for equal exponent and modulus */
823 return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
824 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
825 /*
826 return equal_mp_ints(exp, pvar->hosts_state.key_exp)
827 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
828 */
829
830 case KEY_RSA: // SSH2 RSA host public key
831 return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
832 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
833 BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
834
835 case KEY_DSA: // SSH2 DSA host public key
836 return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
837 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
838 BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
839 BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
840 BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
841
842 case KEY_ECDSA256:
843 case KEY_ECDSA384:
844 case KEY_ECDSA521:
845 if (key->ecdsa == NULL || pvar->hosts_state.hostkey.ecdsa == NULL) {
846 return FALSE;
847 }
848 group = EC_KEY_get0_group(key->ecdsa);
849 pa = EC_KEY_get0_public_key(key->ecdsa),
850 pb = EC_KEY_get0_public_key(pvar->hosts_state.hostkey.ecdsa);
851 return EC_POINT_cmp(group, pa, pb, NULL) == 0;
852
853 default:
854 return FALSE;
855 }
856
857 }
858
859 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
860 {
861 char buf[1024];
862 char buf2[2048];
863 int i, j;
864 int ch;
865 char *fp = NULL;
866
867 // static text�� # �������z�X�g�����u������
868 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
869 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
870 buf2[i] = ch;
871 }
872 strncpy_s(buf2 + i, sizeof(buf2) - i,
873 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
874 j = i + strlen(buf2 + i);
875 for (; buf[i] == '#'; i++) {
876 }
877 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
878
879 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
880
881 // fingerprint����������
882 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX);
883 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
884 free(fp);
885
886 // �r�W���A����fingerprint���\������
887 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART);
888 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
889 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
890 free(fp);
891 }
892
893 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
894 {
895 int i = 0, j, k;
896 BIGNUM *num = BN_new();
897 int ch;
898
899 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
900
901 do {
902 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
903 i++;
904 } while (!BN_is_zero(num));
905
906 /* we need to reverse the digits */
907 for (j = 0, k = i - 1; j < k; j++, k--) {
908 ch = buf[j];
909 buf[j] = buf[k];
910 buf[k] = ch;
911 }
912
913 buf[i] = 0;
914 return i;
915 }
916
917 //
918 // known_hosts �t�@�C�������������G���g�������������B
919 //
920 static char FAR *format_host_key(PTInstVar pvar)
921 {
922 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
923 char *result = NULL;
924 int index;
925 ssh_keytype type = pvar->hosts_state.hostkey.type;
926
927 switch (type) {
928 case KEY_RSA1:
929 {
930 int result_len = host_len + 50 + 8 +
931 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
932 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
933 result = (char FAR *) malloc(result_len);
934
935 if (pvar->ssh_state.tcpport == 22) {
936 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
937 index = host_len;
938 }
939 else {
940 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
941 pvar->hosts_state.prefetched_hostname,
942 pvar->ssh_state.tcpport);
943 index = strlen(result);
944 }
945
946 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
947 " %d ", pvar->hosts_state.hostkey.bits);
948 index += strlen(result + index);
949 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
950 result[index] = ' ';
951 index++;
952 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
953 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
954
955 break;
956 }
957
958 case KEY_RSA:
959 case KEY_DSA:
960 case KEY_ECDSA256:
961 case KEY_ECDSA384:
962 case KEY_ECDSA521:
963 {
964 Key *key = &pvar->hosts_state.hostkey;
965 char *blob = NULL;
966 int blen, uulen, msize;
967 char *uu = NULL;
968 int n;
969
970 key_to_blob(key, &blob, &blen);
971 uulen = 2 * blen;
972 uu = malloc(uulen);
973 if (uu == NULL) {
974 goto error;
975 }
976 n = uuencode(blob, blen, uu, uulen);
977 if (n > 0) {
978 msize = host_len + 50 + uulen;
979 result = malloc(msize);
980 if (result == NULL) {
981 goto error;
982 }
983
984 // setup
985 if (pvar->ssh_state.tcpport == 22) {
986 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
987 pvar->hosts_state.prefetched_hostname,
988 get_sshname_from_key(key),
989 uu);
990 } else {
991 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
992 pvar->hosts_state.prefetched_hostname,
993 pvar->ssh_state.tcpport,
994 get_sshname_from_key(key),
995 uu);
996 }
997 }
998 error:
999 if (blob != NULL)
1000 free(blob);
1001 if (uu != NULL)
1002 free(uu);
1003
1004 break;
1005 }
1006
1007 default:
1008 return NULL;
1009
1010 }
1011
1012 return result;
1013 }
1014
1015 static void add_host_key(PTInstVar pvar)
1016 {
1017 char FAR *name = NULL;
1018
1019 if ( pvar->hosts_state.file_names != NULL)
1020 name = pvar->hosts_state.file_names[0];
1021
1022 if (name == NULL || name[0] == 0) {
1023 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1024 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1025 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1026 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1027 } else {
1028 char FAR *keydata = format_host_key(pvar);
1029 int length = strlen(keydata);
1030 int fd;
1031 int amount_written;
1032 int close_result;
1033 char buf[FILENAME_MAX];
1034
1035 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1036 fd = _open(buf,
1037 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1038 _S_IREAD | _S_IWRITE);
1039 if (fd == -1) {
1040 if (errno == EACCES) {
1041 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1042 "An error occurred while trying to write the host key.\n"
1043 "You do not have permission to write to the known-hosts file.");
1044 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1045 } else {
1046 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1047 "An error occurred while trying to write the host key.\n"
1048 "The host key could not be written.");
1049 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1050 }
1051 return;
1052 }
1053
1054 amount_written = _write(fd, keydata, length);
1055 free(keydata);
1056 close_result = _close(fd);
1057
1058 if (amount_written != length || close_result == -1) {
1059 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1060 "An error occurred while trying to write the host key.\n"
1061 "The host key could not be written.");
1062 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1063 }
1064 }
1065 }
1066
1067 static char FAR *copy_mp_int(char FAR * num)
1068 {
1069 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1070 char FAR *result = (char FAR *) malloc(len);
1071
1072 if (result != NULL) {
1073 memcpy(result, num, len);
1074 }
1075
1076 return result;
1077 }
1078
1079 //
1080 // �����z�X�g�����e���������L�[����������
1081 // add_host_key ����������������
1082 //
1083 static void delete_different_key(PTInstVar pvar)
1084 {
1085 char FAR *name = pvar->hosts_state.file_names[0];
1086
1087 if (name == NULL || name[0] == 0) {
1088 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1089 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1090 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1091 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1092 }
1093 else {
1094 Key key; // ���������z�X�g���L�[
1095 int length;
1096 char filename[MAX_PATH];
1097 char tmp[L_tmpnam];
1098 int fd;
1099 int amount_written = 0;
1100 int close_result;
1101 int data_index = 0;
1102 char buf[FILENAME_MAX];
1103
1104 // �������������t�@�C�����J��
1105 _getcwd(filename, sizeof(filename));
1106 tmpnam_s(tmp,sizeof(tmp));
1107 strcat_s(filename, sizeof(filename), tmp);
1108 fd = _open(filename,
1109 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1110 _S_IREAD | _S_IWRITE);
1111
1112 if (fd == -1) {
1113 if (errno == EACCES) {
1114 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1115 "An error occurred while trying to write the host key.\n"
1116 "You do not have permission to write to the known-hosts file.");
1117 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1118 } else {
1119 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1120 "An error occurred while trying to write the host key.\n"
1121 "The host key could not be written.");
1122 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1123 }
1124 return;
1125 }
1126
1127 // ���������T�[�o���L�[����������
1128 switch (pvar->hosts_state.hostkey.type) {
1129 case KEY_RSA1: // SSH1
1130 key.type = KEY_RSA1;
1131 key.bits = pvar->hosts_state.hostkey.bits;
1132 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1133 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1134 break;
1135 case KEY_RSA: // SSH2 RSA
1136 key.type = KEY_RSA;
1137 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1138 break;
1139 case KEY_DSA: // SSH2 DSA
1140 key.type = KEY_DSA;
1141 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1142 break;
1143 case KEY_ECDSA256:
1144 case KEY_ECDSA384:
1145 case KEY_ECDSA521:
1146 key.type = pvar->hosts_state.hostkey.type;
1147 key.ecdsa = EC_KEY_dup(pvar->hosts_state.hostkey.ecdsa);
1148 break;
1149 }
1150
1151 // �t�@�C��������������
1152 begin_read_host_files(pvar, 0);
1153 do {
1154 int host_index = 0;
1155 int matched = 0;
1156 int keybits = 0;
1157 char FAR *data;
1158 int do_write = 0;
1159 length = amount_written = 0;
1160
1161 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1162 break;
1163 }
1164
1165 if (data_index == pvar->hosts_state.file_data_index) {
1166 // index ���i������ == ��������������
1167 break;
1168 }
1169
1170 data = pvar->hosts_state.file_data + data_index;
1171 host_index = eat_spaces(data);
1172
1173 if (data[host_index] == '#') {
1174 do_write = 1;
1175 }
1176 else {
1177 // �z�X�g������
1178 host_index--;
1179 do {
1180 int negated;
1181 int bracketed;
1182 char *end_bracket;
1183 int host_matched = 0;
1184 unsigned short keyfile_port = 22;
1185
1186 host_index++;
1187 negated = data[host_index] == '!';
1188
1189 if (negated) {
1190 host_index++;
1191 bracketed = data[host_index] == '[';
1192 if (bracketed) {
1193 end_bracket = strstr(data + host_index + 1, "]:");
1194 if (end_bracket != NULL) {
1195 *end_bracket = ' ';
1196 host_index++;
1197 }
1198 }
1199 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1200 if (bracketed && end_bracket != NULL) {
1201 *end_bracket = ']';
1202 keyfile_port = atoi(end_bracket + 2);
1203 }
1204 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1205 matched = 0;
1206 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1207 host_index--;
1208 do {
1209 host_index++;
1210 host_index += eat_to_end_of_pattern(data + host_index);
1211 } while (data[host_index] == ',');
1212 break;
1213 }
1214 }
1215 else {
1216 bracketed = data[host_index] == '[';
1217 if (bracketed) {
1218 end_bracket = strstr(data + host_index + 1, "]:");
1219 if (end_bracket != NULL) {
1220 *end_bracket = ' ';
1221 host_index++;
1222 }
1223 }
1224 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1225 if (bracketed && end_bracket != NULL) {
1226 *end_bracket = ']';
1227 keyfile_port = atoi(end_bracket + 2);
1228 }
1229 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1230 matched = 1;
1231 }
1232 }
1233 host_index += eat_to_end_of_pattern(data + host_index);
1234 } while (data[host_index] == ',');
1235
1236 // �z�X�g������������
1237 if (!matched) {
1238 do_write = 1;
1239 }
1240 // �z�X�g��������
1241 else {
1242 // �����`�������� or ���v�����L�[
1243 if (match_key(pvar, &key) != 0) {
1244 do_write = 1;
1245 }
1246 // �����`�������������v�������L�[���X�L�b�v������
1247 }
1248 }
1249
1250 // ������������
1251 if (do_write) {
1252 length = pvar->hosts_state.file_data_index - data_index;
1253 amount_written =
1254 _write(fd, pvar->hosts_state.file_data + data_index,
1255 length);
1256
1257 if (amount_written != length) {
1258 goto error1;
1259 }
1260 }
1261 data_index = pvar->hosts_state.file_data_index;
1262 } while (1); // ������������
1263
1264 error1:
1265 close_result = _close(fd);
1266 if (amount_written != length || close_result == -1) {
1267 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1268 "An error occurred while trying to write the host key.\n"
1269 "The host key could not be written.");
1270 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1271 goto error2;
1272 }
1273
1274 // �������������t�@�C���������l�[��
1275 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1276 _unlink(buf);
1277 rename(filename, buf);
1278
1279 error2:
1280 _unlink(filename);
1281
1282 finish_read_host_files(pvar, 0);
1283 }
1284 }
1285
1286 //
1287 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1288 // ���[�U���m�F�������B
1289 // TODO: finger print���\�����s���B
1290 // (2006.3.25 yutaka)
1291 //
1292 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1293 LPARAM lParam)
1294 {
1295 PTInstVar pvar;
1296 LOGFONT logfont;
1297 HFONT font;
1298 char uimsg[MAX_UIMSG];
1299
1300 switch (msg) {
1301 case WM_INITDIALOG:
1302 pvar = (PTInstVar) lParam;
1303 pvar->hosts_state.hosts_dialog = dlg;
1304 SetWindowLong(dlg, DWL_USER, lParam);
1305
1306 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1307 GetWindowText(dlg, uimsg, sizeof(uimsg));
1308 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1309 SetWindowText(dlg, pvar->ts->UIMsg);
1310 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1311 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING", pvar, uimsg);
1312 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1313 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1314 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING2", pvar, uimsg);
1315 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1316 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1317 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1318 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1319 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1320 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1321 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1322 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1323 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1324 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1325 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1326 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1327 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1328
1329 switch (pvar->dns_key_check) {
1330 case DNS_VERIFY_NOTFOUND:
1331 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "SSHFP RR not found.");
1332 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1333 break;
1334 case DNS_VERIFY_MATCH:
1335 case DNS_VERIFY_AUTH_MATCH:
1336 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "SSHFP RR found and match.");
1337 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1338 break;
1339 case DNS_VERIFY_MISMATCH:
1340 case DNS_VERIFY_AUTH_MISMATCH:
1341 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "SSHFP RR found but not match.");
1342 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1343 break;
1344 case DNS_VERIFY_DIFFERENTTYPE:
1345 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1346 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "SSHFP RR found but different type.");
1347 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1348 break;
1349 }
1350
1351 switch (pvar->dns_key_check) {
1352 case DNS_VERIFY_MATCH:
1353 case DNS_VERIFY_MISMATCH:
1354 case DNS_VERIFY_DIFFERENTTYPE:
1355 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "SSHFP RR is *not* authenticated by DNSSEC.");
1356 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1357 break;
1358 case DNS_VERIFY_AUTH_MATCH:
1359 case DNS_VERIFY_AUTH_MISMATCH:
1360 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1361 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "SSHFP RR is authenticated by DNSSEC.");
1362 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1363 break;
1364 }
1365
1366 init_hosts_dlg(pvar, dlg);
1367
1368 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1369 GetObject(font, sizeof(LOGFONT), &logfont);
1370 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1371 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1372 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1373 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1374 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1375 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1376 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1377 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1378 }
1379 else {
1380 DlgHostsAddFont = NULL;
1381 }
1382
1383 // add host check box���`�F�b�N���f�t�H���g������������
1384 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1385
1386 return TRUE; /* because we do not set the focus */
1387
1388 case WM_COMMAND:
1389 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1390
1391 switch (LOWORD(wParam)) {
1392 case IDC_CONTINUE:
1393 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1394 add_host_key(pvar);
1395 }
1396
1397 if (SSHv1(pvar)) {
1398 SSH_notify_host_OK(pvar);
1399 } else { // SSH2
1400 // SSH2���������� SSH_notify_host_OK() �������B
1401 }
1402
1403 pvar->hosts_state.hosts_dialog = NULL;
1404
1405 EndDialog(dlg, 1);
1406
1407 if (DlgHostsAddFont != NULL) {
1408 DeleteObject(DlgHostsAddFont);
1409 }
1410
1411 return TRUE;
1412
1413 case IDCANCEL: /* kill the connection */
1414 pvar->hosts_state.hosts_dialog = NULL;
1415 notify_closed_connection(pvar);
1416 EndDialog(dlg, 0);
1417
1418 if (DlgHostsAddFont != NULL) {
1419 DeleteObject(DlgHostsAddFont);
1420 }
1421
1422 return TRUE;
1423
1424 default:
1425 return FALSE;
1426 }
1427
1428 default:
1429 return FALSE;
1430 }
1431 }
1432
1433 //
1434 // �u�����������m�F�_�C�A���O������
1435 //
1436 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1437 LPARAM lParam)
1438 {
1439 PTInstVar pvar;
1440 LOGFONT logfont;
1441 HFONT font;
1442 char uimsg[MAX_UIMSG];
1443
1444 switch (msg) {
1445 case WM_INITDIALOG:
1446 pvar = (PTInstVar) lParam;
1447 pvar->hosts_state.hosts_dialog = dlg;
1448 SetWindowLong(dlg, DWL_USER, lParam);
1449
1450 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1451 GetWindowText(dlg, uimsg, sizeof(uimsg));
1452 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
1453 SetWindowText(dlg, pvar->ts->UIMsg);
1454 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1455 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
1456 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1457 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1458 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
1459 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1460 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1461 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
1462 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1463 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1464 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
1465 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1466 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1467 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1468 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1469 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1470 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1471 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1472
1473 switch (pvar->dns_key_check) {
1474 case DNS_VERIFY_NOTFOUND:
1475 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "SSHFP RR not found.");
1476 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1477 break;
1478 case DNS_VERIFY_MATCH:
1479 case DNS_VERIFY_AUTH_MATCH:
1480 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "SSHFP RR found and match.");
1481 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1482 break;
1483 case DNS_VERIFY_MISMATCH:
1484 case DNS_VERIFY_AUTH_MISMATCH:
1485 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "SSHFP RR found but not match.");
1486 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1487 break;
1488 case DNS_VERIFY_DIFFERENTTYPE:
1489 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1490 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "SSHFP RR found but different type.");
1491 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1492 break;
1493 }
1494
1495 switch (pvar->dns_key_check) {
1496 case DNS_VERIFY_MATCH:
1497 case DNS_VERIFY_MISMATCH:
1498 case DNS_VERIFY_DIFFERENTTYPE:
1499 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "SSHFP RR is *not* authenticated by DNSSEC.");
1500 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1501 break;
1502 case DNS_VERIFY_AUTH_MATCH:
1503 case DNS_VERIFY_AUTH_MISMATCH:
1504 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1505 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "SSHFP RR is authenticated by DNSSEC.");
1506 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1507 break;
1508 }
1509
1510 init_hosts_dlg(pvar, dlg);
1511
1512 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1513 GetObject(font, sizeof(LOGFONT), &logfont);
1514 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1515 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1516 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1517 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1518 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1519 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1520 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1521 }
1522 else {
1523 DlgHostsReplaceFont = NULL;
1524 }
1525
1526 // �f�t�H���g���`�F�b�N����������
1527 return TRUE; /* because we do not set the focus */
1528
1529 case WM_COMMAND:
1530 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1531
1532 switch (LOWORD(wParam)) {
1533 case IDC_CONTINUE:
1534 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1535 add_host_key(pvar);
1536 delete_different_key(pvar);
1537 }
1538
1539 if (SSHv1(pvar)) {
1540 SSH_notify_host_OK(pvar);
1541 } else { // SSH2
1542 // SSH2���������� SSH_notify_host_OK() �������B
1543 }
1544
1545 pvar->hosts_state.hosts_dialog = NULL;
1546
1547 EndDialog(dlg, 1);
1548
1549 if (DlgHostsReplaceFont != NULL) {
1550 DeleteObject(DlgHostsReplaceFont);
1551 }
1552
1553 return TRUE;
1554
1555 case IDCANCEL: /* kill the connection */
1556 pvar->hosts_state.hosts_dialog = NULL;
1557 notify_closed_connection(pvar);
1558 EndDialog(dlg, 0);
1559
1560 if (DlgHostsReplaceFont != NULL) {
1561 DeleteObject(DlgHostsReplaceFont);
1562 }
1563
1564 return TRUE;
1565
1566 default:
1567 return FALSE;
1568 }
1569
1570 default:
1571 return FALSE;
1572 }
1573 }
1574
1575 //
1576 // �����z�X�g�����`�����������������m�F�_�C�A���O������
1577 //
1578 static BOOL CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1579 LPARAM lParam)
1580 {
1581 PTInstVar pvar;
1582 LOGFONT logfont;
1583 HFONT font;
1584 char uimsg[MAX_UIMSG];
1585
1586 switch (msg) {
1587 case WM_INITDIALOG:
1588 pvar = (PTInstVar) lParam;
1589 pvar->hosts_state.hosts_dialog = dlg;
1590 SetWindowLong(dlg, DWL_USER, lParam);
1591
1592 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1593 GetWindowText(dlg, uimsg, sizeof(uimsg));
1594 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
1595 SetWindowText(dlg, pvar->ts->UIMsg);
1596 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1597 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
1598 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1599 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1600 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
1601 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1602 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1603 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
1604 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1605 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1606 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
1607 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1608 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1609 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1610 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1611 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1612 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1613 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1614
1615 switch (pvar->dns_key_check) {
1616 case DNS_VERIFY_NOTFOUND:
1617 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "SSHFP RR not found.");
1618 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1619 break;
1620 case DNS_VERIFY_MATCH:
1621 case DNS_VERIFY_AUTH_MATCH:
1622 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "SSHFP RR found and match.");
1623 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1624 break;
1625 case DNS_VERIFY_MISMATCH:
1626 case DNS_VERIFY_AUTH_MISMATCH:
1627 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "SSHFP RR found but not match.");
1628 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1629 break;
1630 case DNS_VERIFY_DIFFERENTTYPE:
1631 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1632 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "SSHFP RR found but different type.");
1633 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1634 break;
1635 }
1636
1637 switch (pvar->dns_key_check) {
1638 case DNS_VERIFY_MATCH:
1639 case DNS_VERIFY_MISMATCH:
1640 case DNS_VERIFY_DIFFERENTTYPE:
1641 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "SSHFP RR is *not* authenticated by DNSSEC.");
1642 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1643 break;
1644 case DNS_VERIFY_AUTH_MATCH:
1645 case DNS_VERIFY_AUTH_MISMATCH:
1646 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1647 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "SSHFP RR is authenticated by DNSSEC.");
1648 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1649 break;
1650 }
1651
1652 init_hosts_dlg(pvar, dlg);
1653
1654 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1655 GetObject(font, sizeof(LOGFONT), &logfont);
1656 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1657 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1658 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1659 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1660 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1661 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1662 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1663 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1664 }
1665 else {
1666 DlgHostsAddFont = NULL;
1667 }
1668
1669 // add host check box ���f�t�H���g�� off ������
1670 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1671
1672 return TRUE; /* because we do not set the focus */
1673
1674 case WM_COMMAND:
1675 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1676
1677 switch (LOWORD(wParam)) {
1678 case IDC_CONTINUE:
1679 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1680 add_host_key(pvar);
1681 }
1682
1683 if (SSHv1(pvar)) {
1684 SSH_notify_host_OK(pvar);
1685 } else { // SSH2
1686 // SSH2���������� SSH_notify_host_OK() �������B
1687 }
1688
1689 pvar->hosts_state.hosts_dialog = NULL;
1690
1691 EndDialog(dlg, 1);
1692
1693 if (DlgHostsAddFont != NULL) {
1694 DeleteObject(DlgHostsAddFont);
1695 }
1696
1697 return TRUE;
1698
1699 case IDCANCEL: /* kill the connection */
1700 pvar->hosts_state.hosts_dialog = NULL;
1701 notify_closed_connection(pvar);
1702 EndDialog(dlg, 0);
1703
1704 if (DlgHostsAddFont != NULL) {
1705 DeleteObject(DlgHostsAddFont);
1706 }
1707
1708 return TRUE;
1709
1710 default:
1711 return FALSE;
1712 }
1713
1714 default:
1715 return FALSE;
1716 }
1717 }
1718
1719 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1720 {
1721 if (pvar->hosts_state.hosts_dialog == NULL) {
1722 HWND cur_active = GetActiveWindow();
1723
1724 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1725 cur_active != NULL ? cur_active : wnd,
1726 hosts_add_dlg_proc, (LPARAM) pvar);
1727 }
1728 }
1729
1730 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
1731 {
1732 if (pvar->hosts_state.hosts_dialog == NULL) {
1733 HWND cur_active = GetActiveWindow();
1734
1735 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
1736 cur_active != NULL ? cur_active : wnd,
1737 hosts_replace_dlg_proc, (LPARAM) pvar);
1738 }
1739 }
1740
1741 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
1742 {
1743 if (pvar->hosts_state.hosts_dialog == NULL) {
1744 HWND cur_active = GetActiveWindow();
1745
1746 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
1747 cur_active != NULL ? cur_active : wnd,
1748 hosts_add2_dlg_proc, (LPARAM) pvar);
1749 }
1750 }
1751
1752 int is_numeric_hostname(const char *hostname)
1753 {
1754 struct addrinfo hints, *ai;
1755
1756 if (hostname == NULL) {
1757 return -1;
1758 }
1759
1760 memset(&hints, 0, sizeof(hints));
1761 hints.ai_socktype = SOCK_DGRAM;
1762 hints.ai_flags = AI_NUMERICHOST;
1763
1764 if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
1765 freeaddrinfo(ai);
1766 return 1;
1767 }
1768
1769 return 0;
1770 }
1771
1772 int verify_hostkey_dns(char FAR *hostname, Key *key)
1773 {
1774 DNS_STATUS status;
1775 PDNS_RECORD rec, p;
1776 PDNS_SSHFP_DATA t;
1777 int hostkey_alg, hostkey_dtype, hostkey_dlen;
1778 BYTE *hostkey_digest;
1779 int found = DNS_VERIFY_NOTFOUND;
1780
1781 switch (key->type) {
1782 case KEY_RSA:
1783 hostkey_alg = SSHFP_KEY_RSA;
1784 hostkey_dtype = SSHFP_HASH_SHA1;
1785 break;
1786 case KEY_DSA:
1787 hostkey_alg = SSHFP_KEY_DSA;
1788 hostkey_dtype = SSHFP_HASH_SHA1;
1789 break;
1790 case KEY_ECDSA256:
1791 case KEY_ECDSA384:
1792 case KEY_ECDSA521:
1793 hostkey_alg = SSHFP_KEY_ECDSA;
1794 hostkey_dtype = SSHFP_HASH_SHA256;
1795 break;
1796 default: // Un-supported algorithm
1797 hostkey_alg = SSHFP_KEY_RESERVED;
1798 hostkey_dtype = SSHFP_HASH_RESERVED;
1799 }
1800
1801 if (hostkey_alg) {
1802 hostkey_digest = key_fingerprint_raw(key, hostkey_dtype, &hostkey_dlen);
1803 }
1804 else {
1805 hostkey_digest = NULL;
1806 }
1807
1808 status = DnsQuery(hostname, DNS_TYPE_SSHFP, DNS_QUERY_STANDARD, NULL, &rec, NULL);
1809
1810 if (status == 0) {
1811 for (p=rec; p!=NULL; p=p->pNext) {
1812 if (p->wType == DNS_TYPE_SSHFP) {
1813 t = (PDNS_SSHFP_DATA)&(p->Data.Null);
1814 if (t->Algorithm == hostkey_alg && t->DigestType == hostkey_dtype) {
1815 if (hostkey_dlen == p->wDataLength-2 && memcmp(hostkey_digest, t->Digest, hostkey_dlen) == 0) {
1816 found = DNS_VERIFY_MATCH;
1817 break;
1818 }
1819 else {
1820 found = DNS_VERIFY_MISMATCH;
1821 break;
1822 }
1823 }
1824 else {
1825 found = DNS_VERIFY_DIFFERENTTYPE;
1826 }
1827 }
1828 }
1829 }
1830
1831 free(hostkey_digest);
1832 DnsRecordListFree(rec, DnsFreeRecordList);
1833 return found;
1834 }
1835
1836 //
1837 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1838 //
1839 // SSH2���������� (2006.3.24 yutaka)
1840 //
1841 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1842 {
1843 int found_different_key = 0, found_different_type_key = 0;
1844
1845 pvar->dns_key_check = DNS_VERIFY_NONE;
1846
1847 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1848 if (pvar->hosts_state.prefetched_hostname != NULL
1849 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1850 && match_key(pvar, key) == 1) {
1851
1852 if (SSHv1(pvar)) {
1853 SSH_notify_host_OK(pvar);
1854 } else {
1855 // SSH2���������� SSH_notify_host_OK() �������B
1856 }
1857 return TRUE;
1858 }
1859
1860 // �������������������������A�������_���t�@�C��������������
1861 if (begin_read_host_files(pvar, 0)) {
1862 do {
1863 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1864 break;
1865 }
1866
1867 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1868 int match = match_key(pvar, key);
1869 if (match == 1) {
1870 finish_read_host_files(pvar, 0);
1871 // ���������G���g�����Q�������A���v�����L�[�������������������B
1872 // SSH2���������������������������B(2006.3.29 yutaka)
1873 if (SSHv1(pvar)) {
1874 SSH_notify_host_OK(pvar);
1875 } else {
1876 // SSH2���������� SSH_notify_host_OK() �������B
1877 }
1878 return TRUE;
1879 }
1880 else if (match == 0) {
1881 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1882 found_different_key = 1;
1883 }
1884 else {
1885 // �L�[���`������������
1886 found_different_type_key = 1;
1887 }
1888 }
1889 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1890
1891 finish_read_host_files(pvar, 0);
1892 }
1893
1894 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1895 pvar->hosts_state.hostkey.type = key->type;
1896 switch (key->type) {
1897 case KEY_RSA1: // SSH1
1898 pvar->hosts_state.hostkey.bits = key->bits;
1899 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1900 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1901 break;
1902 case KEY_RSA: // SSH2 RSA
1903 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1904 break;
1905 case KEY_DSA: // SSH2 DSA
1906 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1907 break;
1908 case KEY_ECDSA256: // SSH2 ECDSA
1909 case KEY_ECDSA384:
1910 case KEY_ECDSA521:
1911 pvar->hosts_state.hostkey.ecdsa = EC_KEY_dup(key->ecdsa);
1912 break;
1913 }
1914 free(pvar->hosts_state.prefetched_hostname);
1915 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1916
1917 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
1918 if (pvar->nocheck_known_hosts == TRUE) {
1919 return TRUE;
1920 }
1921
1922 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
1923 pvar->dns_key_check = verify_hostkey_dns(hostname, key);
1924 }
1925
1926 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1927 // �������K�v�����������A�����R�[�������X�����B
1928 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1929 // (2007.10.1 yutaka)
1930 if (found_different_key) {
1931 HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar);
1932 }
1933 else if (found_different_type_key) {
1934 HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar);
1935 }
1936 else {
1937 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1938 }
1939
1940 return TRUE;
1941 }
1942
1943 void HOSTS_notify_disconnecting(PTInstVar pvar)
1944 {
1945 if (pvar->hosts_state.hosts_dialog != NULL) {
1946 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
1947 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1948 EnableWindow(pvar->NotificationWindow, TRUE);
1949 }
1950 }
1951
1952 void HOSTS_end(PTInstVar pvar)
1953 {
1954 int i;
1955
1956 free(pvar->hosts_state.prefetched_hostname);
1957 init_hostkey(&pvar->hosts_state.hostkey);
1958
1959 if (pvar->hosts_state.file_names != NULL) {
1960 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1961 free(pvar->hosts_state.file_names[i]);
1962 }
1963 free(pvar->hosts_state.file_names);
1964 }
1965 }

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