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

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