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 2992 - (show annotations) (download) (as text)
Wed Aug 8 16:04:09 2007 UTC (16 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 44571 byte(s)
安全な関数を使用するように変更した。

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

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