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

サーバから送られてきた鍵候補群と、known_hosts ファイルを検索し、
鍵のマッチングを行うようにした。


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

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