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 5843 - (show annotations) (download) (as text)
Fri May 1 07:44:21 2015 UTC (8 years, 11 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 55955 byte(s)
チケット #35047 SSH サーバホスト公開鍵の自動更新

公開鍵の重複チェックを行う関数を HOSTS_compare_public_key() として切り出した。

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

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