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 4565 - (show annotations) (download) (as text)
Tue Aug 2 11:50:35 2011 UTC (12 years, 8 months ago) by maya
File MIME type: text/x-csrc
File size: 56896 byte(s)
新しいラベルにフォントを適用
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_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1374 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1375 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1376 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1377 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1378 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1379 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1380 }
1381 else {
1382 DlgHostsAddFont = NULL;
1383 }
1384
1385 // add host check box���`�F�b�N���f�t�H���g������������
1386 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1387
1388 return TRUE; /* because we do not set the focus */
1389
1390 case WM_COMMAND:
1391 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1392
1393 switch (LOWORD(wParam)) {
1394 case IDC_CONTINUE:
1395 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1396 add_host_key(pvar);
1397 }
1398
1399 if (SSHv1(pvar)) {
1400 SSH_notify_host_OK(pvar);
1401 } else { // SSH2
1402 // SSH2���������� SSH_notify_host_OK() �������B
1403 }
1404
1405 pvar->hosts_state.hosts_dialog = NULL;
1406
1407 EndDialog(dlg, 1);
1408
1409 if (DlgHostsAddFont != NULL) {
1410 DeleteObject(DlgHostsAddFont);
1411 }
1412
1413 return TRUE;
1414
1415 case IDCANCEL: /* kill the connection */
1416 pvar->hosts_state.hosts_dialog = NULL;
1417 notify_closed_connection(pvar);
1418 EndDialog(dlg, 0);
1419
1420 if (DlgHostsAddFont != NULL) {
1421 DeleteObject(DlgHostsAddFont);
1422 }
1423
1424 return TRUE;
1425
1426 default:
1427 return FALSE;
1428 }
1429
1430 default:
1431 return FALSE;
1432 }
1433 }
1434
1435 //
1436 // �u�����������m�F�_�C�A���O������
1437 //
1438 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1439 LPARAM lParam)
1440 {
1441 PTInstVar pvar;
1442 LOGFONT logfont;
1443 HFONT font;
1444 char uimsg[MAX_UIMSG];
1445
1446 switch (msg) {
1447 case WM_INITDIALOG:
1448 pvar = (PTInstVar) lParam;
1449 pvar->hosts_state.hosts_dialog = dlg;
1450 SetWindowLong(dlg, DWL_USER, lParam);
1451
1452 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1453 GetWindowText(dlg, uimsg, sizeof(uimsg));
1454 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
1455 SetWindowText(dlg, pvar->ts->UIMsg);
1456 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1457 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
1458 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1459 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1460 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
1461 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1462 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1463 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
1464 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1465 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1466 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
1467 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1468 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1469 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1470 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1471 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1472 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1473 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1474
1475 switch (pvar->dns_key_check) {
1476 case DNS_VERIFY_NOTFOUND:
1477 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "SSHFP RR not found.");
1478 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1479 break;
1480 case DNS_VERIFY_MATCH:
1481 case DNS_VERIFY_AUTH_MATCH:
1482 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "SSHFP RR found and match.");
1483 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1484 break;
1485 case DNS_VERIFY_MISMATCH:
1486 case DNS_VERIFY_AUTH_MISMATCH:
1487 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "SSHFP RR found but not match.");
1488 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1489 break;
1490 case DNS_VERIFY_DIFFERENTTYPE:
1491 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1492 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "SSHFP RR found but different type.");
1493 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1494 break;
1495 }
1496
1497 switch (pvar->dns_key_check) {
1498 case DNS_VERIFY_MATCH:
1499 case DNS_VERIFY_MISMATCH:
1500 case DNS_VERIFY_DIFFERENTTYPE:
1501 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "SSHFP RR is *not* authenticated by DNSSEC.");
1502 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1503 break;
1504 case DNS_VERIFY_AUTH_MATCH:
1505 case DNS_VERIFY_AUTH_MISMATCH:
1506 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1507 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "SSHFP RR is authenticated by DNSSEC.");
1508 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1509 break;
1510 }
1511
1512 init_hosts_dlg(pvar, dlg);
1513
1514 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1515 GetObject(font, sizeof(LOGFONT), &logfont);
1516 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1517 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1518 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1519 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1520 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1521 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1522 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1523 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1524 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1525 }
1526 else {
1527 DlgHostsReplaceFont = NULL;
1528 }
1529
1530 // �f�t�H���g���`�F�b�N����������
1531 return TRUE; /* because we do not set the focus */
1532
1533 case WM_COMMAND:
1534 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1535
1536 switch (LOWORD(wParam)) {
1537 case IDC_CONTINUE:
1538 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1539 add_host_key(pvar);
1540 delete_different_key(pvar);
1541 }
1542
1543 if (SSHv1(pvar)) {
1544 SSH_notify_host_OK(pvar);
1545 } else { // SSH2
1546 // SSH2���������� SSH_notify_host_OK() �������B
1547 }
1548
1549 pvar->hosts_state.hosts_dialog = NULL;
1550
1551 EndDialog(dlg, 1);
1552
1553 if (DlgHostsReplaceFont != NULL) {
1554 DeleteObject(DlgHostsReplaceFont);
1555 }
1556
1557 return TRUE;
1558
1559 case IDCANCEL: /* kill the connection */
1560 pvar->hosts_state.hosts_dialog = NULL;
1561 notify_closed_connection(pvar);
1562 EndDialog(dlg, 0);
1563
1564 if (DlgHostsReplaceFont != NULL) {
1565 DeleteObject(DlgHostsReplaceFont);
1566 }
1567
1568 return TRUE;
1569
1570 default:
1571 return FALSE;
1572 }
1573
1574 default:
1575 return FALSE;
1576 }
1577 }
1578
1579 //
1580 // �����z�X�g�����`�����������������m�F�_�C�A���O������
1581 //
1582 static BOOL CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1583 LPARAM lParam)
1584 {
1585 PTInstVar pvar;
1586 LOGFONT logfont;
1587 HFONT font;
1588 char uimsg[MAX_UIMSG];
1589
1590 switch (msg) {
1591 case WM_INITDIALOG:
1592 pvar = (PTInstVar) lParam;
1593 pvar->hosts_state.hosts_dialog = dlg;
1594 SetWindowLong(dlg, DWL_USER, lParam);
1595
1596 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1597 GetWindowText(dlg, uimsg, sizeof(uimsg));
1598 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
1599 SetWindowText(dlg, pvar->ts->UIMsg);
1600 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1601 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
1602 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1603 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1604 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
1605 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1606 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1607 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
1608 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1609 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1610 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
1611 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1612 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1613 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1614 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1615 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1616 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1617 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1618
1619 switch (pvar->dns_key_check) {
1620 case DNS_VERIFY_NOTFOUND:
1621 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "SSHFP RR not found.");
1622 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1623 break;
1624 case DNS_VERIFY_MATCH:
1625 case DNS_VERIFY_AUTH_MATCH:
1626 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "SSHFP RR found and match.");
1627 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1628 break;
1629 case DNS_VERIFY_MISMATCH:
1630 case DNS_VERIFY_AUTH_MISMATCH:
1631 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "SSHFP RR found but not match.");
1632 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1633 break;
1634 case DNS_VERIFY_DIFFERENTTYPE:
1635 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1636 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "SSHFP RR found but different type.");
1637 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1638 break;
1639 }
1640
1641 switch (pvar->dns_key_check) {
1642 case DNS_VERIFY_MATCH:
1643 case DNS_VERIFY_MISMATCH:
1644 case DNS_VERIFY_DIFFERENTTYPE:
1645 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "SSHFP RR is *not* authenticated by DNSSEC.");
1646 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1647 break;
1648 case DNS_VERIFY_AUTH_MATCH:
1649 case DNS_VERIFY_AUTH_MISMATCH:
1650 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1651 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "SSHFP RR is authenticated by DNSSEC.");
1652 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1653 break;
1654 }
1655
1656 init_hosts_dlg(pvar, dlg);
1657
1658 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1659 GetObject(font, sizeof(LOGFONT), &logfont);
1660 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1661 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1662 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1663 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1664 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1665 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1666 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1667 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1668 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1669 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1670 }
1671 else {
1672 DlgHostsAddFont = NULL;
1673 }
1674
1675 // add host check box ���f�t�H���g�� off ������
1676 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1677
1678 return TRUE; /* because we do not set the focus */
1679
1680 case WM_COMMAND:
1681 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1682
1683 switch (LOWORD(wParam)) {
1684 case IDC_CONTINUE:
1685 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1686 add_host_key(pvar);
1687 }
1688
1689 if (SSHv1(pvar)) {
1690 SSH_notify_host_OK(pvar);
1691 } else { // SSH2
1692 // SSH2���������� SSH_notify_host_OK() �������B
1693 }
1694
1695 pvar->hosts_state.hosts_dialog = NULL;
1696
1697 EndDialog(dlg, 1);
1698
1699 if (DlgHostsAddFont != NULL) {
1700 DeleteObject(DlgHostsAddFont);
1701 }
1702
1703 return TRUE;
1704
1705 case IDCANCEL: /* kill the connection */
1706 pvar->hosts_state.hosts_dialog = NULL;
1707 notify_closed_connection(pvar);
1708 EndDialog(dlg, 0);
1709
1710 if (DlgHostsAddFont != NULL) {
1711 DeleteObject(DlgHostsAddFont);
1712 }
1713
1714 return TRUE;
1715
1716 default:
1717 return FALSE;
1718 }
1719
1720 default:
1721 return FALSE;
1722 }
1723 }
1724
1725 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1726 {
1727 if (pvar->hosts_state.hosts_dialog == NULL) {
1728 HWND cur_active = GetActiveWindow();
1729
1730 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1731 cur_active != NULL ? cur_active : wnd,
1732 hosts_add_dlg_proc, (LPARAM) pvar);
1733 }
1734 }
1735
1736 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
1737 {
1738 if (pvar->hosts_state.hosts_dialog == NULL) {
1739 HWND cur_active = GetActiveWindow();
1740
1741 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
1742 cur_active != NULL ? cur_active : wnd,
1743 hosts_replace_dlg_proc, (LPARAM) pvar);
1744 }
1745 }
1746
1747 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
1748 {
1749 if (pvar->hosts_state.hosts_dialog == NULL) {
1750 HWND cur_active = GetActiveWindow();
1751
1752 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
1753 cur_active != NULL ? cur_active : wnd,
1754 hosts_add2_dlg_proc, (LPARAM) pvar);
1755 }
1756 }
1757
1758 int is_numeric_hostname(const char *hostname)
1759 {
1760 struct addrinfo hints, *ai;
1761
1762 if (hostname == NULL) {
1763 return -1;
1764 }
1765
1766 memset(&hints, 0, sizeof(hints));
1767 hints.ai_socktype = SOCK_DGRAM;
1768 hints.ai_flags = AI_NUMERICHOST;
1769
1770 if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
1771 freeaddrinfo(ai);
1772 return 1;
1773 }
1774
1775 return 0;
1776 }
1777
1778 int verify_hostkey_dns(char FAR *hostname, Key *key)
1779 {
1780 DNS_STATUS status;
1781 PDNS_RECORD rec, p;
1782 PDNS_SSHFP_DATA t;
1783 int hostkey_alg, hostkey_dtype, hostkey_dlen;
1784 BYTE *hostkey_digest;
1785 int found = DNS_VERIFY_NOTFOUND;
1786
1787 switch (key->type) {
1788 case KEY_RSA:
1789 hostkey_alg = SSHFP_KEY_RSA;
1790 hostkey_dtype = SSHFP_HASH_SHA1;
1791 break;
1792 case KEY_DSA:
1793 hostkey_alg = SSHFP_KEY_DSA;
1794 hostkey_dtype = SSHFP_HASH_SHA1;
1795 break;
1796 case KEY_ECDSA256:
1797 case KEY_ECDSA384:
1798 case KEY_ECDSA521:
1799 hostkey_alg = SSHFP_KEY_ECDSA;
1800 hostkey_dtype = SSHFP_HASH_SHA256;
1801 break;
1802 default: // Un-supported algorithm
1803 hostkey_alg = SSHFP_KEY_RESERVED;
1804 hostkey_dtype = SSHFP_HASH_RESERVED;
1805 }
1806
1807 if (hostkey_alg) {
1808 hostkey_digest = key_fingerprint_raw(key, hostkey_dtype, &hostkey_dlen);
1809 }
1810 else {
1811 hostkey_digest = NULL;
1812 }
1813
1814 status = DnsQuery(hostname, DNS_TYPE_SSHFP, DNS_QUERY_STANDARD, NULL, &rec, NULL);
1815
1816 if (status == 0) {
1817 for (p=rec; p!=NULL; p=p->pNext) {
1818 if (p->wType == DNS_TYPE_SSHFP) {
1819 t = (PDNS_SSHFP_DATA)&(p->Data.Null);
1820 if (t->Algorithm == hostkey_alg && t->DigestType == hostkey_dtype) {
1821 if (hostkey_dlen == p->wDataLength-2 && memcmp(hostkey_digest, t->Digest, hostkey_dlen) == 0) {
1822 found = DNS_VERIFY_MATCH;
1823 break;
1824 }
1825 else {
1826 found = DNS_VERIFY_MISMATCH;
1827 break;
1828 }
1829 }
1830 else {
1831 found = DNS_VERIFY_DIFFERENTTYPE;
1832 }
1833 }
1834 }
1835 }
1836
1837 free(hostkey_digest);
1838 DnsRecordListFree(rec, DnsFreeRecordList);
1839 return found;
1840 }
1841
1842 //
1843 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1844 //
1845 // SSH2���������� (2006.3.24 yutaka)
1846 //
1847 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1848 {
1849 int found_different_key = 0, found_different_type_key = 0;
1850
1851 pvar->dns_key_check = DNS_VERIFY_NONE;
1852
1853 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1854 if (pvar->hosts_state.prefetched_hostname != NULL
1855 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1856 && match_key(pvar, key) == 1) {
1857
1858 if (SSHv1(pvar)) {
1859 SSH_notify_host_OK(pvar);
1860 } else {
1861 // SSH2���������� SSH_notify_host_OK() �������B
1862 }
1863 return TRUE;
1864 }
1865
1866 // �������������������������A�������_���t�@�C��������������
1867 if (begin_read_host_files(pvar, 0)) {
1868 do {
1869 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1870 break;
1871 }
1872
1873 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1874 int match = match_key(pvar, key);
1875 if (match == 1) {
1876 finish_read_host_files(pvar, 0);
1877 // ���������G���g�����Q�������A���v�����L�[�������������������B
1878 // SSH2���������������������������B(2006.3.29 yutaka)
1879 if (SSHv1(pvar)) {
1880 SSH_notify_host_OK(pvar);
1881 } else {
1882 // SSH2���������� SSH_notify_host_OK() �������B
1883 }
1884 return TRUE;
1885 }
1886 else if (match == 0) {
1887 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1888 found_different_key = 1;
1889 }
1890 else {
1891 // �L�[���`������������
1892 found_different_type_key = 1;
1893 }
1894 }
1895 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1896
1897 finish_read_host_files(pvar, 0);
1898 }
1899
1900 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1901 pvar->hosts_state.hostkey.type = key->type;
1902 switch (key->type) {
1903 case KEY_RSA1: // SSH1
1904 pvar->hosts_state.hostkey.bits = key->bits;
1905 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1906 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1907 break;
1908 case KEY_RSA: // SSH2 RSA
1909 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1910 break;
1911 case KEY_DSA: // SSH2 DSA
1912 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1913 break;
1914 case KEY_ECDSA256: // SSH2 ECDSA
1915 case KEY_ECDSA384:
1916 case KEY_ECDSA521:
1917 pvar->hosts_state.hostkey.ecdsa = EC_KEY_dup(key->ecdsa);
1918 break;
1919 }
1920 free(pvar->hosts_state.prefetched_hostname);
1921 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1922
1923 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
1924 if (pvar->nocheck_known_hosts == TRUE) {
1925 return TRUE;
1926 }
1927
1928 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
1929 pvar->dns_key_check = verify_hostkey_dns(hostname, key);
1930 }
1931
1932 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1933 // �������K�v�����������A�����R�[�������X�����B
1934 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1935 // (2007.10.1 yutaka)
1936 if (found_different_key) {
1937 HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar);
1938 }
1939 else if (found_different_type_key) {
1940 HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar);
1941 }
1942 else {
1943 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1944 }
1945
1946 return TRUE;
1947 }
1948
1949 void HOSTS_notify_disconnecting(PTInstVar pvar)
1950 {
1951 if (pvar->hosts_state.hosts_dialog != NULL) {
1952 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
1953 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1954 EnableWindow(pvar->NotificationWindow, TRUE);
1955 }
1956 }
1957
1958 void HOSTS_end(PTInstVar pvar)
1959 {
1960 int i;
1961
1962 free(pvar->hosts_state.prefetched_hostname);
1963 init_hostkey(&pvar->hosts_state.hostkey);
1964
1965 if (pvar->hosts_state.file_names != NULL) {
1966 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1967 free(pvar->hosts_state.file_names[i]);
1968 }
1969 free(pvar->hosts_state.file_names);
1970 }
1971 }

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