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

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