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 6132 - (show annotations) (download) (as text)
Sun Nov 15 10:25:50 2015 UTC (8 years, 4 months ago) by maya
File MIME type: text/x-csrc
File size: 74117 byte(s)
SSH ホスト鍵の fingerprint の表示を、MD5 形式か SHA256 形式か選択できるようにした
  https://osdn.jp/ticket/browse.php?group_id=1412&tid=35602
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 hosts_dlg_set_fingerprint(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg)
1078 {
1079 char *fp = NULL;
1080
1081 // fingerprint����������
1082 switch (dgst_alg) {
1083 case SSH_DIGEST_MD5:
1084 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX, dgst_alg);
1085 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
1086 free(fp);
1087 break;
1088 case SSH_DIGEST_SHA256:
1089 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_BASE64, dgst_alg);
1090 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
1091 free(fp);
1092 break;
1093 }
1094
1095 // �r�W���A����fingerprint���\������
1096 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART, dgst_alg);
1097 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
1098 free(fp);
1099 }
1100
1101 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
1102 {
1103 char buf[1024];
1104 char buf2[2048];
1105 int i, j;
1106 int ch;
1107
1108 // static text�� # �������z�X�g�����u������
1109 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
1110 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
1111 buf2[i] = ch;
1112 }
1113 strncpy_s(buf2 + i, sizeof(buf2) - i,
1114 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
1115 j = i + strlen(buf2 + i);
1116 for (; buf[i] == '#'; i++) {
1117 }
1118 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
1119
1120 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
1121
1122 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
1123
1124 CheckDlgButton(dlg, IDC_FP_HASH_ALG_MD5, TRUE);
1125 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
1126 }
1127
1128 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
1129 {
1130 int i = 0, j, k;
1131 BIGNUM *num = BN_new();
1132 int ch;
1133
1134 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
1135
1136 do {
1137 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
1138 i++;
1139 } while (!BN_is_zero(num));
1140
1141 /* we need to reverse the digits */
1142 for (j = 0, k = i - 1; j < k; j++, k--) {
1143 ch = buf[j];
1144 buf[j] = buf[k];
1145 buf[k] = ch;
1146 }
1147
1148 buf[i] = 0;
1149 return i;
1150 }
1151
1152 //
1153 // known_hosts �t�@�C�������������G���g�������������B
1154 //
1155 static char FAR *format_host_key(PTInstVar pvar)
1156 {
1157 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
1158 char *result = NULL;
1159 int index;
1160 ssh_keytype type = pvar->hosts_state.hostkey.type;
1161
1162 switch (type) {
1163 case KEY_RSA1:
1164 {
1165 int result_len = host_len + 50 + 8 +
1166 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
1167 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
1168 result = (char FAR *) malloc(result_len);
1169
1170 if (pvar->ssh_state.tcpport == 22) {
1171 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
1172 index = host_len;
1173 }
1174 else {
1175 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1176 pvar->hosts_state.prefetched_hostname,
1177 pvar->ssh_state.tcpport);
1178 index = strlen(result);
1179 }
1180
1181 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
1182 " %d ", pvar->hosts_state.hostkey.bits);
1183 index += strlen(result + index);
1184 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
1185 result[index] = ' ';
1186 index++;
1187 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
1188 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1189
1190 break;
1191 }
1192
1193 case KEY_RSA:
1194 case KEY_DSA:
1195 case KEY_ECDSA256:
1196 case KEY_ECDSA384:
1197 case KEY_ECDSA521:
1198 case KEY_ED25519:
1199 {
1200 Key *key = &pvar->hosts_state.hostkey;
1201 char *blob = NULL;
1202 int blen, uulen, msize;
1203 char *uu = NULL;
1204 int n;
1205
1206 key_to_blob(key, &blob, &blen);
1207 uulen = 2 * blen;
1208 uu = malloc(uulen);
1209 if (uu == NULL) {
1210 goto error;
1211 }
1212 n = uuencode(blob, blen, uu, uulen);
1213 if (n > 0) {
1214 msize = host_len + 50 + uulen;
1215 result = malloc(msize);
1216 if (result == NULL) {
1217 goto error;
1218 }
1219
1220 // setup
1221 if (pvar->ssh_state.tcpport == 22) {
1222 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1223 pvar->hosts_state.prefetched_hostname,
1224 get_sshname_from_key(key),
1225 uu);
1226 } else {
1227 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1228 pvar->hosts_state.prefetched_hostname,
1229 pvar->ssh_state.tcpport,
1230 get_sshname_from_key(key),
1231 uu);
1232 }
1233 }
1234 error:
1235 if (blob != NULL)
1236 free(blob);
1237 if (uu != NULL)
1238 free(uu);
1239
1240 break;
1241 }
1242
1243 default:
1244 return NULL;
1245
1246 }
1247
1248 return result;
1249 }
1250
1251 static char FAR *format_specified_host_key(Key *key, char *hostname, unsigned short tcpport)
1252 {
1253 int host_len = strlen(hostname);
1254 char *result = NULL;
1255 int index;
1256 ssh_keytype type = key->type;
1257
1258 switch (type) {
1259 case KEY_RSA1:
1260 {
1261 int result_len = host_len + 50 + 8 +
1262 get_ushort16_MSBfirst(key->exp) / 3 +
1263 get_ushort16_MSBfirst(key->mod) / 3;
1264 result = (char FAR *) malloc(result_len);
1265
1266 if (tcpport == 22) {
1267 strncpy_s(result, result_len, hostname, _TRUNCATE);
1268 index = host_len;
1269 }
1270 else {
1271 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
1272 hostname,
1273 tcpport);
1274 index = strlen(result);
1275 }
1276
1277 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
1278 " %d ", key->bits);
1279 index += strlen(result + index);
1280 index += print_mp_int(result + index, key->exp);
1281 result[index] = ' ';
1282 index++;
1283 index += print_mp_int(result + index, key->mod);
1284 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
1285
1286 break;
1287 }
1288
1289 case KEY_RSA:
1290 case KEY_DSA:
1291 case KEY_ECDSA256:
1292 case KEY_ECDSA384:
1293 case KEY_ECDSA521:
1294 case KEY_ED25519:
1295 {
1296 //Key *key = &pvar->hosts_state.hostkey;
1297 char *blob = NULL;
1298 int blen, uulen, msize;
1299 char *uu = NULL;
1300 int n;
1301
1302 key_to_blob(key, &blob, &blen);
1303 uulen = 2 * blen;
1304 uu = malloc(uulen);
1305 if (uu == NULL) {
1306 goto error;
1307 }
1308 n = uuencode(blob, blen, uu, uulen);
1309 if (n > 0) {
1310 msize = host_len + 50 + uulen;
1311 result = malloc(msize);
1312 if (result == NULL) {
1313 goto error;
1314 }
1315
1316 // setup
1317 if (tcpport == 22) {
1318 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
1319 hostname,
1320 get_sshname_from_key(key),
1321 uu);
1322 }
1323 else {
1324 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
1325 hostname,
1326 tcpport,
1327 get_sshname_from_key(key),
1328 uu);
1329 }
1330 }
1331 error:
1332 if (blob != NULL)
1333 free(blob);
1334 if (uu != NULL)
1335 free(uu);
1336
1337 break;
1338 }
1339
1340 default:
1341 return NULL;
1342
1343 }
1344
1345 return result;
1346 }
1347
1348 static void add_host_key(PTInstVar pvar)
1349 {
1350 char FAR *name = NULL;
1351
1352 if ( pvar->hosts_state.file_names != NULL)
1353 name = pvar->hosts_state.file_names[0];
1354
1355 if (name == NULL || name[0] == 0) {
1356 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1357 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1358 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1359 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1360 } else {
1361 char FAR *keydata = format_host_key(pvar);
1362 int length = strlen(keydata);
1363 int fd;
1364 int amount_written;
1365 int close_result;
1366 char buf[FILENAME_MAX];
1367
1368 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1369 fd = _open(buf,
1370 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1371 _S_IREAD | _S_IWRITE);
1372 if (fd == -1) {
1373 if (errno == EACCES) {
1374 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1375 "An error occurred while trying to write the host key.\n"
1376 "You do not have permission to write to the known-hosts file.");
1377 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1378 } else {
1379 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1380 "An error occurred while trying to write the host key.\n"
1381 "The host key could not be written.");
1382 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1383 }
1384 return;
1385 }
1386
1387 amount_written = _write(fd, keydata, length);
1388 free(keydata);
1389 close_result = _close(fd);
1390
1391 if (amount_written != length || close_result == -1) {
1392 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1393 "An error occurred while trying to write the host key.\n"
1394 "The host key could not be written.");
1395 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1396 }
1397 }
1398 }
1399
1400 // �w�������L�[�� known_hosts �����������B
1401 void HOSTS_add_host_key(PTInstVar pvar, Key *key)
1402 {
1403 char FAR *name = NULL;
1404 char *hostname;
1405 unsigned short tcpport;
1406
1407 hostname = pvar->ssh_state.hostname;
1408 tcpport = pvar->ssh_state.tcpport;
1409
1410 if (pvar->hosts_state.file_names != NULL)
1411 name = pvar->hosts_state.file_names[0];
1412
1413 if (name == NULL || name[0] == 0) {
1414 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1415 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1416 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1417 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1418 }
1419 else {
1420 char FAR *keydata = format_specified_host_key(key, hostname, tcpport);
1421 int length = strlen(keydata);
1422 int fd;
1423 int amount_written;
1424 int close_result;
1425 char buf[FILENAME_MAX];
1426
1427 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1428 fd = _open(buf,
1429 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
1430 _S_IREAD | _S_IWRITE);
1431 if (fd == -1) {
1432 if (errno == EACCES) {
1433 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1434 "An error occurred while trying to write the host key.\n"
1435 "You do not have permission to write to the known-hosts file.");
1436 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1437 }
1438 else {
1439 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1440 "An error occurred while trying to write the host key.\n"
1441 "The host key could not be written.");
1442 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1443 }
1444 return;
1445 }
1446
1447 amount_written = _write(fd, keydata, length);
1448 free(keydata);
1449 close_result = _close(fd);
1450
1451 if (amount_written != length || close_result == -1) {
1452 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1453 "An error occurred while trying to write the host key.\n"
1454 "The host key could not be written.");
1455 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1456 }
1457 }
1458 }
1459
1460 static char FAR *copy_mp_int(char FAR * num)
1461 {
1462 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1463 char FAR *result = (char FAR *) malloc(len);
1464
1465 if (result != NULL) {
1466 memcpy(result, num, len);
1467 }
1468
1469 return result;
1470 }
1471
1472 //
1473 // �����z�X�g�����e���������L�[����������
1474 // add_host_key ����������������
1475 //
1476 static void delete_different_key(PTInstVar pvar)
1477 {
1478 char FAR *name = pvar->hosts_state.file_names[0];
1479
1480 if (name == NULL || name[0] == 0) {
1481 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1482 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1483 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1484 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1485 }
1486 else {
1487 Key key; // ���������z�X�g���L�[
1488 Key *key_freed;
1489 int length;
1490 char filename[MAX_PATH];
1491 char tmp[L_tmpnam];
1492 int fd;
1493 int amount_written = 0;
1494 int close_result;
1495 int data_index = 0;
1496 char buf[FILENAME_MAX];
1497
1498 // �������������t�@�C�����J��
1499 _getcwd(filename, sizeof(filename));
1500 tmpnam_s(tmp,sizeof(tmp));
1501 strcat_s(filename, sizeof(filename), tmp);
1502 fd = _open(filename,
1503 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1504 _S_IREAD | _S_IWRITE);
1505
1506 if (fd == -1) {
1507 if (errno == EACCES) {
1508 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1509 "An error occurred while trying to write the host key.\n"
1510 "You do not have permission to write to the known-hosts file.");
1511 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1512 } else {
1513 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1514 "An error occurred while trying to write the host key.\n"
1515 "The host key could not be written.");
1516 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1517 }
1518 return;
1519 }
1520
1521 // ���������T�[�o���L�[����������
1522 memset(&key, 0, sizeof(key));
1523 switch (pvar->hosts_state.hostkey.type) {
1524 case KEY_RSA1: // SSH1
1525 key.type = KEY_RSA1;
1526 key.bits = pvar->hosts_state.hostkey.bits;
1527 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1528 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1529 break;
1530 case KEY_RSA: // SSH2 RSA
1531 key.type = KEY_RSA;
1532 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1533 break;
1534 case KEY_DSA: // SSH2 DSA
1535 key.type = KEY_DSA;
1536 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1537 break;
1538 case KEY_ECDSA256:
1539 case KEY_ECDSA384:
1540 case KEY_ECDSA521:
1541 key.type = pvar->hosts_state.hostkey.type;
1542 key.ecdsa = EC_KEY_dup(pvar->hosts_state.hostkey.ecdsa);
1543 break;
1544 case KEY_ED25519:
1545 key.type = pvar->hosts_state.hostkey.type;
1546 key.ed25519_pk = duplicate_ED25519_PK(pvar->hosts_state.hostkey.ed25519_pk);
1547 break;
1548 }
1549
1550 // �t�@�C��������������
1551 begin_read_host_files(pvar, 0);
1552 do {
1553 int host_index = 0;
1554 int matched = 0;
1555 int keybits = 0;
1556 char FAR *data;
1557 int do_write = 0;
1558 length = amount_written = 0;
1559
1560 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1561 break;
1562 }
1563
1564 if (data_index == pvar->hosts_state.file_data_index) {
1565 // index ���i������ == ��������������
1566 break;
1567 }
1568
1569 data = pvar->hosts_state.file_data + data_index;
1570 host_index = eat_spaces(data);
1571
1572 if (data[host_index] == '#') {
1573 do_write = 1;
1574 }
1575 else {
1576 // �z�X�g������
1577 host_index--;
1578 do {
1579 int negated;
1580 int bracketed;
1581 char *end_bracket;
1582 int host_matched = 0;
1583 unsigned short keyfile_port = 22;
1584
1585 host_index++;
1586 negated = data[host_index] == '!';
1587
1588 if (negated) {
1589 host_index++;
1590 bracketed = data[host_index] == '[';
1591 if (bracketed) {
1592 end_bracket = strstr(data + host_index + 1, "]:");
1593 if (end_bracket != NULL) {
1594 *end_bracket = ' ';
1595 host_index++;
1596 }
1597 }
1598 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1599 if (bracketed && end_bracket != NULL) {
1600 *end_bracket = ']';
1601 keyfile_port = atoi(end_bracket + 2);
1602 }
1603 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1604 matched = 0;
1605 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1606 host_index--;
1607 do {
1608 host_index++;
1609 host_index += eat_to_end_of_pattern(data + host_index);
1610 } while (data[host_index] == ',');
1611 break;
1612 }
1613 }
1614 else {
1615 bracketed = data[host_index] == '[';
1616 if (bracketed) {
1617 end_bracket = strstr(data + host_index + 1, "]:");
1618 if (end_bracket != NULL) {
1619 *end_bracket = ' ';
1620 host_index++;
1621 }
1622 }
1623 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1624 if (bracketed && end_bracket != NULL) {
1625 *end_bracket = ']';
1626 keyfile_port = atoi(end_bracket + 2);
1627 }
1628 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1629 matched = 1;
1630 }
1631 }
1632 host_index += eat_to_end_of_pattern(data + host_index);
1633 } while (data[host_index] == ',');
1634
1635 // �z�X�g������������
1636 if (!matched) {
1637 do_write = 1;
1638 }
1639 // �z�X�g��������
1640 else {
1641 // �����`�������� or ���v�����L�[
1642 if (match_key(pvar, &key) != 0) {
1643 do_write = 1;
1644 }
1645 // �����`�������������v�������L�[���X�L�b�v������
1646 }
1647 }
1648
1649 // ������������
1650 if (do_write) {
1651 length = pvar->hosts_state.file_data_index - data_index;
1652 amount_written =
1653 _write(fd, pvar->hosts_state.file_data + data_index,
1654 length);
1655
1656 if (amount_written != length) {
1657 goto error1;
1658 }
1659 }
1660 data_index = pvar->hosts_state.file_data_index;
1661 } while (1); // ������������
1662
1663 error1:
1664 close_result = _close(fd);
1665 if (amount_written != length || close_result == -1) {
1666 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1667 "An error occurred while trying to write the host key.\n"
1668 "The host key could not be written.");
1669 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1670 goto error2;
1671 }
1672
1673 // �������������t�@�C���������l�[��
1674 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1675 _unlink(buf);
1676 rename(filename, buf);
1677
1678 error2:
1679 _unlink(filename);
1680
1681 finish_read_host_files(pvar, 0);
1682
1683 // ���������������������������B
1684 key_freed = key_new(KEY_UNSPEC);
1685 memcpy(key_freed, &key, sizeof(Key));
1686 key_free(key_freed);
1687 }
1688 }
1689
1690
1691 void HOSTS_delete_all_hostkeys(PTInstVar pvar)
1692 {
1693 char FAR *name = pvar->hosts_state.file_names[0];
1694 char *hostname;
1695 unsigned short tcpport;
1696
1697 hostname = pvar->ssh_state.hostname;
1698 tcpport = pvar->ssh_state.tcpport;
1699
1700 if (name == NULL || name[0] == 0) {
1701 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1702 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1703 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1704 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1705 }
1706 else {
1707 Key key; // ���������z�X�g���L�[
1708 Key *key_freed;
1709 int length;
1710 char filename[MAX_PATH];
1711 char tmp[L_tmpnam];
1712 int fd;
1713 int amount_written = 0;
1714 int close_result;
1715 int data_index = 0;
1716 char buf[FILENAME_MAX];
1717
1718 // �������������t�@�C�����J��
1719 _getcwd(filename, sizeof(filename));
1720 tmpnam_s(tmp, sizeof(tmp));
1721 strcat_s(filename, sizeof(filename), tmp);
1722 fd = _open(filename,
1723 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1724 _S_IREAD | _S_IWRITE);
1725
1726 if (fd == -1) {
1727 if (errno == EACCES) {
1728 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1729 "An error occurred while trying to write the host key.\n"
1730 "You do not have permission to write to the known-hosts file.");
1731 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1732 }
1733 else {
1734 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1735 "An error occurred while trying to write the host key.\n"
1736 "The host key could not be written.");
1737 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1738 }
1739 return;
1740 }
1741
1742 // ���������T�[�o���L�[����������
1743 memset(&key, 0, sizeof(key));
1744 switch (pvar->hosts_state.hostkey.type) {
1745 case KEY_RSA1: // SSH1
1746 key.type = KEY_RSA1;
1747 key.bits = pvar->hosts_state.hostkey.bits;
1748 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1749 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1750 break;
1751 case KEY_RSA: // SSH2 RSA
1752 key.type = KEY_RSA;
1753 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1754 break;
1755 case KEY_DSA: // SSH2 DSA
1756 key.type = KEY_DSA;
1757 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1758 break;
1759 case KEY_ECDSA256:
1760 case KEY_ECDSA384:
1761 case KEY_ECDSA521:
1762 key.type = pvar->hosts_state.hostkey.type;
1763 key.ecdsa = EC_KEY_dup(pvar->hosts_state.hostkey.ecdsa);
1764 break;
1765 case KEY_ED25519:
1766 key.type = pvar->hosts_state.hostkey.type;
1767 key.ed25519_pk = duplicate_ED25519_PK(pvar->hosts_state.hostkey.ed25519_pk);
1768 break;
1769 }
1770
1771 // �t�@�C��������������
1772 begin_read_host_files(pvar, 0);
1773 do {
1774 int host_index = 0;
1775 int matched = 0;
1776 int keybits = 0;
1777 char FAR *data;
1778 int do_write = 0;
1779 length = amount_written = 0;
1780
1781 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1782 break;
1783 }
1784
1785 if (data_index == pvar->hosts_state.file_data_index) {
1786 // index ���i������ == ��������������
1787 break;
1788 }
1789
1790 data = pvar->hosts_state.file_data + data_index;
1791 host_index = eat_spaces(data);
1792
1793 if (data[host_index] == '#') {
1794 do_write = 1;
1795 }
1796 else {
1797 // �z�X�g������
1798 host_index--;
1799 do {
1800 int negated;
1801 int bracketed;
1802 char *end_bracket;
1803 int host_matched = 0;
1804 unsigned short keyfile_port = 22;
1805
1806 host_index++;
1807 negated = data[host_index] == '!';
1808
1809 if (negated) {
1810 host_index++;
1811 bracketed = data[host_index] == '[';
1812 if (bracketed) {
1813 end_bracket = strstr(data + host_index + 1, "]:");
1814 if (end_bracket != NULL) {
1815 *end_bracket = ' ';
1816 host_index++;
1817 }
1818 }
1819 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1820 if (bracketed && end_bracket != NULL) {
1821 *end_bracket = ']';
1822 keyfile_port = atoi(end_bracket + 2);
1823 }
1824 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1825 matched = 0;
1826 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1827 host_index--;
1828 do {
1829 host_index++;
1830 host_index += eat_to_end_of_pattern(data + host_index);
1831 } while (data[host_index] == ',');
1832 break;
1833 }
1834 }
1835 else {
1836 bracketed = data[host_index] == '[';
1837 if (bracketed) {
1838 end_bracket = strstr(data + host_index + 1, "]:");
1839 if (end_bracket != NULL) {
1840 *end_bracket = ' ';
1841 host_index++;
1842 }
1843 }
1844 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1845 if (bracketed && end_bracket != NULL) {
1846 *end_bracket = ']';
1847 keyfile_port = atoi(end_bracket + 2);
1848 }
1849 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1850 matched = 1;
1851 }
1852 }
1853 host_index += eat_to_end_of_pattern(data + host_index);
1854 } while (data[host_index] == ',');
1855
1856 // �z�X�g������������
1857 if (!matched) {
1858 do_write = 1;
1859 }
1860 // �z�X�g��������
1861 else {
1862 // ���������������������B
1863
1864 }
1865 }
1866
1867 // ������������
1868 if (do_write) {
1869 length = pvar->hosts_state.file_data_index - data_index;
1870 amount_written =
1871 _write(fd, pvar->hosts_state.file_data + data_index,
1872 length);
1873
1874 if (amount_written != length) {
1875 goto error1;
1876 }
1877 }
1878 data_index = pvar->hosts_state.file_data_index;
1879 } while (1); // ������������
1880
1881 error1:
1882 close_result = _close(fd);
1883 if (amount_written != length || close_result == -1) {
1884 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1885 "An error occurred while trying to write the host key.\n"
1886 "The host key could not be written.");
1887 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1888 goto error2;
1889 }
1890
1891 // �������������t�@�C���������l�[��
1892 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1893 _unlink(buf);
1894 rename(filename, buf);
1895
1896 error2:
1897 _unlink(filename);
1898
1899 finish_read_host_files(pvar, 0);
1900
1901 // ���������������������������B
1902 key_freed = key_new(KEY_UNSPEC);
1903 memcpy(key_freed, &key, sizeof(Key));
1904 key_free(key_freed);
1905 }
1906 }
1907
1908
1909 //
1910 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1911 // ���[�U���m�F�������B
1912 // TODO: finger print���\�����s���B
1913 // (2006.3.25 yutaka)
1914 //
1915 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1916 LPARAM lParam)
1917 {
1918 PTInstVar pvar;
1919 LOGFONT logfont;
1920 HFONT font;
1921 char uimsg[MAX_UIMSG];
1922
1923 switch (msg) {
1924 case WM_INITDIALOG:
1925 pvar = (PTInstVar) lParam;
1926 pvar->hosts_state.hosts_dialog = dlg;
1927 SetWindowLong(dlg, DWL_USER, lParam);
1928
1929 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1930 GetWindowText(dlg, uimsg, sizeof(uimsg));
1931 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1932 SetWindowText(dlg, pvar->ts->UIMsg);
1933 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1934 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING", pvar, uimsg);
1935 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1936 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1937 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNING2", pvar, uimsg);
1938 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1939 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1940 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1941 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1942 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
1943 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FP_HASH_ALGORITHM", pvar, uimsg);
1944 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
1945 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1946 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1947 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1948 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1949 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1950 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1951 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1952 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1953 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1954
1955 switch (pvar->dns_key_check) {
1956 case DNS_VERIFY_NOTFOUND:
1957 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
1958 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1959 break;
1960 case DNS_VERIFY_MATCH:
1961 case DNS_VERIFY_AUTH_MATCH:
1962 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
1963 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1964 break;
1965 case DNS_VERIFY_MISMATCH:
1966 case DNS_VERIFY_AUTH_MISMATCH:
1967 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
1968 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1969 break;
1970 case DNS_VERIFY_DIFFERENTTYPE:
1971 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1972 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
1973 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
1974 break;
1975 }
1976
1977 switch (pvar->dns_key_check) {
1978 case DNS_VERIFY_MATCH:
1979 case DNS_VERIFY_MISMATCH:
1980 case DNS_VERIFY_DIFFERENTTYPE:
1981 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
1982 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1983 break;
1984 case DNS_VERIFY_AUTH_MATCH:
1985 case DNS_VERIFY_AUTH_MISMATCH:
1986 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
1987 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
1988 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
1989 break;
1990 }
1991
1992 init_hosts_dlg(pvar, dlg);
1993
1994 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1995 GetObject(font, sizeof(LOGFONT), &logfont);
1996 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1997 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1998 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1999 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2000 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2001 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2002 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2003 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2004 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2005 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2006 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2007 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2008 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2009 }
2010 else {
2011 DlgHostsAddFont = NULL;
2012 }
2013
2014 // add host check box���`�F�b�N���f�t�H���g������������
2015 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
2016
2017 return TRUE; /* because we do not set the focus */
2018
2019 case WM_COMMAND:
2020 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2021
2022 switch (LOWORD(wParam)) {
2023 case IDC_CONTINUE:
2024 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2025 if (!pvar->cv->Ready) {
2026 goto canceled;
2027 }
2028
2029 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2030 add_host_key(pvar);
2031 }
2032
2033 if (SSHv1(pvar)) {
2034 SSH_notify_host_OK(pvar);
2035 } else { // SSH2
2036 // SSH2���������� SSH_notify_host_OK() �������B
2037 }
2038
2039 pvar->hosts_state.hosts_dialog = NULL;
2040
2041 EndDialog(dlg, 1);
2042
2043 if (DlgHostsAddFont != NULL) {
2044 DeleteObject(DlgHostsAddFont);
2045 }
2046
2047 return TRUE;
2048
2049 case IDCANCEL: /* kill the connection */
2050 canceled:
2051 pvar->hosts_state.hosts_dialog = NULL;
2052 notify_closed_connection(pvar, "authentication cancelled");
2053 EndDialog(dlg, 0);
2054
2055 if (DlgHostsAddFont != NULL) {
2056 DeleteObject(DlgHostsAddFont);
2057 }
2058
2059 return TRUE;
2060
2061 case IDC_FP_HASH_ALG_MD5:
2062 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2063 return TRUE;
2064
2065 case IDC_FP_HASH_ALG_SHA256:
2066 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2067 return TRUE;
2068
2069 default:
2070 return FALSE;
2071 }
2072
2073 default:
2074 return FALSE;
2075 }
2076 }
2077
2078 //
2079 // �u�����������m�F�_�C�A���O������
2080 //
2081 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2082 LPARAM lParam)
2083 {
2084 PTInstVar pvar;
2085 LOGFONT logfont;
2086 HFONT font;
2087 char uimsg[MAX_UIMSG];
2088
2089 switch (msg) {
2090 case WM_INITDIALOG:
2091 pvar = (PTInstVar) lParam;
2092 pvar->hosts_state.hosts_dialog = dlg;
2093 SetWindowLong(dlg, DWL_USER, lParam);
2094
2095 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2096 GetWindowText(dlg, uimsg, sizeof(uimsg));
2097 UTIL_get_lang_msg("DLG_DIFFERENTKEY_TITLE", pvar, uimsg);
2098 SetWindowText(dlg, pvar->ts->UIMsg);
2099 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
2100 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING", pvar, uimsg);
2101 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2102 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2103 UTIL_get_lang_msg("DLG_DIFFERENTKEY_WARNING2", pvar, uimsg);
2104 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2105 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2106 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FINGERPRINT", pvar, uimsg);
2107 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2108 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2109 UTIL_get_lang_msg("DLG_DIFFERENTKEY_FP_HASH_ALGORITHM", pvar, uimsg);
2110 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2111 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2112 UTIL_get_lang_msg("DLG_DIFFERENTKEY_REPLACE", pvar, uimsg);
2113 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2114 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2115 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2116 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2117 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2118 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2119 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2120
2121 switch (pvar->dns_key_check) {
2122 case DNS_VERIFY_NOTFOUND:
2123 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2124 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2125 break;
2126 case DNS_VERIFY_MATCH:
2127 case DNS_VERIFY_AUTH_MATCH:
2128 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2129 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2130 break;
2131 case DNS_VERIFY_MISMATCH:
2132 case DNS_VERIFY_AUTH_MISMATCH:
2133 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2134 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2135 break;
2136 case DNS_VERIFY_DIFFERENTTYPE:
2137 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2138 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2139 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2140 break;
2141 }
2142
2143 switch (pvar->dns_key_check) {
2144 case DNS_VERIFY_MATCH:
2145 case DNS_VERIFY_MISMATCH:
2146 case DNS_VERIFY_DIFFERENTTYPE:
2147 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2148 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2149 break;
2150 case DNS_VERIFY_AUTH_MATCH:
2151 case DNS_VERIFY_AUTH_MISMATCH:
2152 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2153 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2154 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2155 break;
2156 }
2157
2158 init_hosts_dlg(pvar, dlg);
2159
2160 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2161 GetObject(font, sizeof(LOGFONT), &logfont);
2162 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
2163 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2164 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2165 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2166 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2167 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2168 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2169 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2170 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2171 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE, 0));
2172 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2173 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
2174 }
2175 else {
2176 DlgHostsReplaceFont = NULL;
2177 }
2178
2179 // �f�t�H���g���`�F�b�N����������
2180 return TRUE; /* because we do not set the focus */
2181
2182 case WM_COMMAND:
2183 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2184
2185 switch (LOWORD(wParam)) {
2186 case IDC_CONTINUE:
2187 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2188 if (!pvar->cv->Ready) {
2189 goto canceled;
2190 }
2191
2192 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2193 add_host_key(pvar);
2194 delete_different_key(pvar);
2195 }
2196
2197 if (SSHv1(pvar)) {
2198 SSH_notify_host_OK(pvar);
2199 } else { // SSH2
2200 // SSH2���������� SSH_notify_host_OK() �������B
2201 }
2202
2203 pvar->hosts_state.hosts_dialog = NULL;
2204
2205 EndDialog(dlg, 1);
2206
2207 if (DlgHostsReplaceFont != NULL) {
2208 DeleteObject(DlgHostsReplaceFont);
2209 }
2210
2211 return TRUE;
2212
2213 case IDCANCEL: /* kill the connection */
2214 canceled:
2215 pvar->hosts_state.hosts_dialog = NULL;
2216 notify_closed_connection(pvar, "authentication cancelled");
2217 EndDialog(dlg, 0);
2218
2219 if (DlgHostsReplaceFont != NULL) {
2220 DeleteObject(DlgHostsReplaceFont);
2221 }
2222
2223 return TRUE;
2224
2225 case IDC_FP_HASH_ALG_MD5:
2226 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2227 return TRUE;
2228
2229 case IDC_FP_HASH_ALG_SHA256:
2230 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2231 return TRUE;
2232
2233 default:
2234 return FALSE;
2235 }
2236
2237 default:
2238 return FALSE;
2239 }
2240 }
2241
2242 //
2243 // �����z�X�g�����`�����������������m�F�_�C�A���O������
2244 //
2245 static BOOL CALLBACK hosts_add2_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
2246 LPARAM lParam)
2247 {
2248 PTInstVar pvar;
2249 LOGFONT logfont;
2250 HFONT font;
2251 char uimsg[MAX_UIMSG];
2252
2253 switch (msg) {
2254 case WM_INITDIALOG:
2255 pvar = (PTInstVar) lParam;
2256 pvar->hosts_state.hosts_dialog = dlg;
2257 SetWindowLong(dlg, DWL_USER, lParam);
2258
2259 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
2260 GetWindowText(dlg, uimsg, sizeof(uimsg));
2261 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_TITLE", pvar, uimsg);
2262 SetWindowText(dlg, pvar->ts->UIMsg);
2263 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
2264 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING", pvar, uimsg);
2265 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
2266 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
2267 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_WARNING2", pvar, uimsg);
2268 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
2269 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
2270 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FINGERPRINT", pvar, uimsg);
2271 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
2272 GetDlgItemText(dlg, IDC_FP_HASH_ALG, uimsg, sizeof(uimsg));
2273 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_FP_HASH_ALGORITHM", pvar, uimsg);
2274 SetDlgItemText(dlg, IDC_FP_HASH_ALG, pvar->ts->UIMsg);
2275 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
2276 UTIL_get_lang_msg("DLG_DIFFERENTTYPEKEY_ADD", pvar, uimsg);
2277 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
2278 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
2279 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
2280 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
2281 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2282 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
2283 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2284
2285 switch (pvar->dns_key_check) {
2286 case DNS_VERIFY_NOTFOUND:
2287 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_NOTFOUND", pvar, "No host key fingerprint found in DNS.");
2288 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2289 break;
2290 case DNS_VERIFY_MATCH:
2291 case DNS_VERIFY_AUTH_MATCH:
2292 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MATCH", pvar, "Matching host key fingerprint found in DNS.");
2293 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2294 break;
2295 case DNS_VERIFY_MISMATCH:
2296 case DNS_VERIFY_AUTH_MISMATCH:
2297 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_MISMATCH", pvar, "Mismatching host key fingerprint found in DNS.");
2298 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2299 break;
2300 case DNS_VERIFY_DIFFERENTTYPE:
2301 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2302 UTIL_get_lang_msg("DLG_HOSTKEY_SSHFP_DIFFTYPE", pvar, "Mismatching host key type found in DNS.");
2303 SetDlgItemText(dlg, IDC_HOSTSSHFPCHECK, pvar->ts->UIMsg);
2304 break;
2305 }
2306
2307 switch (pvar->dns_key_check) {
2308 case DNS_VERIFY_MATCH:
2309 case DNS_VERIFY_MISMATCH:
2310 case DNS_VERIFY_DIFFERENTTYPE:
2311 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_NG", pvar, "Found insecure fingerprint in DNS.");
2312 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2313 break;
2314 case DNS_VERIFY_AUTH_MATCH:
2315 case DNS_VERIFY_AUTH_MISMATCH:
2316 case DNS_VERIFY_AUTH_DIFFERENTTYPE:
2317 UTIL_get_lang_msg("DLG_HOSTKEY_DNSSEC_OK", pvar, "Found secure fingerprint in DNS.");
2318 SetDlgItemText(dlg, IDC_HOSTSSHFPDNSSEC, pvar->ts->UIMsg);
2319 break;
2320 }
2321
2322 init_hosts_dlg(pvar, dlg);
2323
2324 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2325 GetObject(font, sizeof(LOGFONT), &logfont);
2326 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
2327 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2328 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2329 SendDlgItemMessage(dlg, IDC_HOSTSSHFPCHECK, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2330 SendDlgItemMessage(dlg, IDC_HOSTSSHFPDNSSEC, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2331 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2332 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2333 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_MD5, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2334 SendDlgItemMessage(dlg, IDC_FP_HASH_ALG_SHA256, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2335 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE, 0));
2336 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2337 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2338 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
2339 }
2340 else {
2341 DlgHostsAddFont = NULL;
2342 }
2343
2344 // add host check box ���f�t�H���g�� off ������
2345 // SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
2346
2347 return TRUE; /* because we do not set the focus */
2348
2349 case WM_COMMAND:
2350 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
2351
2352 switch (LOWORD(wParam)) {
2353 case IDC_CONTINUE:
2354 // �F�������T�[�o�������f�������������A�L�����Z�������������B(2014.3.31 yutaka)
2355 if (!pvar->cv->Ready) {
2356 goto canceled;
2357 }
2358
2359 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
2360 add_host_key(pvar);
2361 }
2362
2363 if (SSHv1(pvar)) {
2364 SSH_notify_host_OK(pvar);
2365 } else { // SSH2
2366 // SSH2���������� SSH_notify_host_OK() �������B
2367 }
2368
2369 pvar->hosts_state.hosts_dialog = NULL;
2370
2371 EndDialog(dlg, 1);
2372
2373 if (DlgHostsAddFont != NULL) {
2374 DeleteObject(DlgHostsAddFont);
2375 }
2376
2377 return TRUE;
2378
2379 case IDCANCEL: /* kill the connection */
2380 canceled:
2381 pvar->hosts_state.hosts_dialog = NULL;
2382 notify_closed_connection(pvar, "authentication cancelled");
2383 EndDialog(dlg, 0);
2384
2385 if (DlgHostsAddFont != NULL) {
2386 DeleteObject(DlgHostsAddFont);
2387 }
2388
2389 return TRUE;
2390
2391 case IDC_FP_HASH_ALG_MD5:
2392 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_MD5);
2393 return TRUE;
2394
2395 case IDC_FP_HASH_ALG_SHA256:
2396 hosts_dlg_set_fingerprint(pvar, dlg, SSH_DIGEST_SHA256);
2397 return TRUE;
2398
2399 default:
2400 return FALSE;
2401 }
2402
2403 default:
2404 return FALSE;
2405 }
2406 }
2407
2408 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
2409 {
2410 if (pvar->hosts_state.hosts_dialog == NULL) {
2411 HWND cur_active = GetActiveWindow();
2412
2413 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
2414 cur_active != NULL ? cur_active : wnd,
2415 hosts_add_dlg_proc, (LPARAM) pvar);
2416 }
2417 }
2418
2419 void HOSTS_do_different_key_dialog(HWND wnd, PTInstVar pvar)
2420 {
2421 if (pvar->hosts_state.hosts_dialog == NULL) {
2422 HWND cur_active = GetActiveWindow();
2423
2424 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTKEY),
2425 cur_active != NULL ? cur_active : wnd,
2426 hosts_replace_dlg_proc, (LPARAM) pvar);
2427 }
2428 }
2429
2430 void HOSTS_do_different_type_key_dialog(HWND wnd, PTInstVar pvar)
2431 {
2432 if (pvar->hosts_state.hosts_dialog == NULL) {
2433 HWND cur_active = GetActiveWindow();
2434
2435 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTTYPEKEY),
2436 cur_active != NULL ? cur_active : wnd,
2437 hosts_add2_dlg_proc, (LPARAM) pvar);
2438 }
2439 }
2440
2441 //
2442 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
2443 //
2444 // SSH2���������� (2006.3.24 yutaka)
2445 //
2446 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
2447 {
2448 int found_different_key = 0, found_different_type_key = 0;
2449
2450 pvar->dns_key_check = DNS_VERIFY_NONE;
2451
2452 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
2453 if (pvar->hosts_state.prefetched_hostname != NULL
2454 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
2455 && match_key(pvar, key) == 1) {
2456
2457 if (SSHv1(pvar)) {
2458 SSH_notify_host_OK(pvar);
2459 } else {
2460 // SSH2���������� SSH_notify_host_OK() �������B
2461 }
2462 return TRUE;
2463 }
2464
2465 // �������������������������A�������_���t�@�C��������������
2466 if (begin_read_host_files(pvar, 0)) {
2467 do {
2468 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
2469 break;
2470 }
2471
2472 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
2473 int match = match_key(pvar, key);
2474 if (match == 1) {
2475 finish_read_host_files(pvar, 0);
2476 // ���������G���g�����Q�������A���v�����L�[�������������������B
2477 // SSH2���������������������������B(2006.3.29 yutaka)
2478 if (SSHv1(pvar)) {
2479 SSH_notify_host_OK(pvar);
2480 } else {
2481 // SSH2���������� SSH_notify_host_OK() �������B
2482 }
2483 return TRUE;
2484 }
2485 else if (match == 0) {
2486 // �L�[�� known_hosts ���������������A�L�[�����e���������B
2487 found_different_key = 1;
2488 }
2489 else {
2490 // �L�[���`������������
2491 found_different_type_key = 1;
2492 }
2493 }
2494 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
2495
2496 finish_read_host_files(pvar, 0);
2497 }
2498
2499 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
2500 pvar->hosts_state.hostkey.type = key->type;
2501 switch (key->type) {
2502 case KEY_RSA1: // SSH1
2503 pvar->hosts_state.hostkey.bits = key->bits;
2504 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
2505 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
2506 break;
2507 case KEY_RSA: // SSH2 RSA
2508 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
2509 break;
2510 case KEY_DSA: // SSH2 DSA
2511 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
2512 break;
2513 case KEY_ECDSA256: // SSH2 ECDSA
2514 case KEY_ECDSA384:
2515 case KEY_ECDSA521:
2516 pvar->hosts_state.hostkey.ecdsa = EC_KEY_dup(key->ecdsa);
2517 break;
2518 case KEY_ED25519:
2519 pvar->hosts_state.hostkey.ed25519_pk = duplicate_ED25519_PK(key->ed25519_pk);
2520 break;
2521 }
2522 free(pvar->hosts_state.prefetched_hostname);
2523 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
2524
2525 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
2526 if (pvar->nocheck_known_hosts == TRUE) {
2527 return TRUE;
2528 }
2529
2530 if (pvar->settings.VerifyHostKeyDNS && !is_numeric_hostname(hostname)) {
2531 pvar->dns_key_check = verify_hostkey_dns(pvar, hostname, key);
2532 }
2533
2534 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
2535 // �������K�v�����������A�����R�[�������X�����B
2536 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
2537 // (2007.10.1 yutaka)
2538 if (found_different_key) {
2539 HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar);
2540 }
2541 else if (found_different_type_key) {
2542 HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar);
2543 }
2544 else {
2545 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
2546 }
2547
2548 return TRUE;
2549 }
2550
2551 void HOSTS_notify_disconnecting(PTInstVar pvar)
2552 {
2553 if (pvar->hosts_state.hosts_dialog != NULL) {
2554 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0);
2555 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
2556 EnableWindow(pvar->NotificationWindow, TRUE);
2557 }
2558 }
2559
2560 void HOSTS_end(PTInstVar pvar)
2561 {
2562 int i;
2563
2564 free(pvar->hosts_state.prefetched_hostname);
2565 init_hostkey(&pvar->hosts_state.hostkey);
2566
2567 if (pvar->hosts_state.file_names != NULL) {
2568 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
2569 free(pvar->hosts_state.file_names[i]);
2570 }
2571 free(pvar->hosts_state.file_names);
2572 }
2573 }

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