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 2995 - (show annotations) (download) (as text)
Wed Aug 15 04:03:26 2007 UTC (16 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 38844 byte(s)
$Log$ を削除した。

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

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