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 3120 - (show annotations) (download) (as text)
Sun Mar 2 13:54:43 2008 UTC (16 years, 1 month ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 39945 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 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 // Key�\�������g���������� (2008.3.2 yutaka)
616 free(key);
617 }
618
619 return index + eat_to_end_of_line(data + index);
620 }
621 }
622
623 //
624 // known_hosts�t�@�C�������z�X�g�������v�����s������
625 //
626 static int read_host_key(PTInstVar pvar, char FAR * hostname,
627 int suppress_errors, int return_always)
628 {
629 int i;
630 int while_flg;
631
632 for (i = 0; hostname[i] != 0; i++) {
633 int ch = hostname[i];
634
635 if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
636 if (!suppress_errors) {
637 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
638 "The host name contains an invalid character.\n"
639 "This session will be terminated.");
640 notify_fatal_error(pvar, pvar->ts->UIMsg);
641 }
642 return 0;
643 }
644 }
645
646 if (i == 0) {
647 if (!suppress_errors) {
648 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
649 "The host name should not be empty.\n"
650 "This session will be terminated.");
651 notify_fatal_error(pvar, pvar->ts->UIMsg);
652 }
653 return 0;
654 }
655
656 #if 0
657 pvar->hosts_state.key_bits = 0;
658 free(pvar->hosts_state.key_exp);
659 pvar->hosts_state.key_exp = NULL;
660 free(pvar->hosts_state.key_mod);
661 pvar->hosts_state.key_mod = NULL;
662 #else
663 // hostkey type is KEY_UNSPEC.
664 init_hostkey(&pvar->hosts_state.hostkey);
665 #endif
666
667 do {
668 if (pvar->hosts_state.file_data == NULL
669 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
670 char FAR *filename;
671 int keep_going = 1;
672
673 if (pvar->hosts_state.file_data != NULL) {
674 end_read_file(pvar, suppress_errors);
675 }
676
677 do {
678 filename =
679 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
680
681 if (filename == NULL) {
682 return 1;
683 } else {
684 pvar->hosts_state.file_num++;
685
686 if (filename[0] != 0) {
687 if (begin_read_file(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 | _O_BINARY,
931 _S_IREAD | _S_IWRITE);
932 if (fd == -1) {
933 if (errno == EACCES) {
934 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
935 "An error occurred while trying to write the host key.\n"
936 "You do not have permission to write to the known-hosts file.");
937 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
938 } else {
939 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
940 "An error occurred while trying to write the host key.\n"
941 "The host key could not be written.");
942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
943 }
944 return;
945 }
946
947 amount_written = _write(fd, keydata, length);
948 free(keydata);
949 close_result = _close(fd);
950
951 if (amount_written != length || close_result == -1) {
952 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
953 "An error occurred while trying to write the host key.\n"
954 "The host key could not be written.");
955 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
956 }
957 }
958 }
959
960 static char FAR *copy_mp_int(char FAR * num)
961 {
962 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
963 char FAR *result = (char FAR *) malloc(len);
964
965 if (result != NULL) {
966 memcpy(result, num, len);
967 }
968
969 return result;
970 }
971
972 //
973 // �����z�X�g�����e���������L�[����������
974 // add_host_key ����������������
975 //
976 static void delete_different_key(PTInstVar pvar)
977 {
978 char FAR *name = pvar->hosts_state.file_names[0];
979
980 if (name == NULL || name[0] == 0) {
981 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
982 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
983 "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
984 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
985 }
986 else {
987 Key key; // ���������z�X�g���L�[
988 int length;
989 char filename[L_tmpnam];
990 int fd;
991 int amount_written = 0;
992 int close_result;
993 int data_index = 0;
994 char buf[FILENAME_MAX];
995
996 // �������������t�@�C�����J��
997 tmpnam(filename);
998 fd = _open(filename,
999 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1000 _S_IREAD | _S_IWRITE);
1001
1002 if (fd == -1) {
1003 if (errno == EACCES) {
1004 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1005 "An error occurred while trying to write the host key.\n"
1006 "You do not have permission to write to the known-hosts file.");
1007 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1008 } else {
1009 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1010 "An error occurred while trying to write the host key.\n"
1011 "The host key could not be written.");
1012 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1013 }
1014 free(filename);
1015 return;
1016 }
1017
1018 // ���������T�[�o���L�[����������
1019 if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1020 key.type = KEY_RSA1;
1021 key.bits = pvar->hosts_state.hostkey.bits;
1022 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1023 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1024 } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1025 key.type = KEY_RSA;
1026 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1027 } else { // SSH2 DSA
1028 key.type = KEY_DSA;
1029 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1030 }
1031
1032 // �t�@�C��������������
1033 begin_read_host_files(pvar, 0);
1034 do {
1035 int host_index = 0;
1036 int matched = 0;
1037 int keybits = 0;
1038 char FAR *data;
1039 int do_write = 0;
1040 length = amount_written = 0;
1041
1042 if (!read_host_key(pvar, pvar->ssh_state.hostname, 0, 1)) {
1043 break;
1044 }
1045
1046 if (data_index == pvar->hosts_state.file_data_index) {
1047 // index ���i������ == ��������������
1048 break;
1049 }
1050
1051 data = pvar->hosts_state.file_data + data_index;
1052 host_index = eat_spaces(data);
1053
1054 if (data[host_index] == '#') {
1055 do_write = 1;
1056 }
1057 else {
1058 // �z�X�g������
1059 host_index--;
1060 do {
1061 int negated;
1062
1063 host_index++;
1064 negated = data[host_index] == '!';
1065
1066 if (negated) {
1067 host_index++;
1068 if (match_pattern(data + host_index,
1069 pvar->ssh_state.hostname)) {
1070 matched = 0;
1071 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1072 host_index--;
1073 do {
1074 host_index++;
1075 host_index += eat_to_end_of_pattern(data + host_index);
1076 } while (data[host_index] == ',');
1077 break;
1078 }
1079 }
1080 else if (match_pattern(data + host_index,
1081 pvar->ssh_state.hostname)) {
1082 matched = 1;
1083 }
1084 host_index += eat_to_end_of_pattern(data + host_index);
1085 } while (data[host_index] == ',');
1086
1087 // �z�X�g�������������v�����L�[����������
1088 if (match_key(pvar, &key)) {
1089 do_write = 1;
1090 }
1091 // �z�X�g������������
1092 else if (!matched) {
1093 do_write = 1;
1094 }
1095 // �z�X�g�������� and �������o�[�W����������
1096 else {
1097 int rsa1_key_bits=0;
1098 rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1099
1100 if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1101 if (!SSHv1(pvar)) {
1102 do_write = 1;
1103 }
1104 }
1105 else { // �t�@�C�����L�[�� ssh2
1106 if (!SSHv2(pvar)) {
1107 do_write = 1;
1108 }
1109 }
1110 }
1111 }
1112
1113 // ������������
1114 if (do_write) {
1115 length = pvar->hosts_state.file_data_index - data_index;
1116 amount_written =
1117 _write(fd, pvar->hosts_state.file_data + data_index,
1118 length);
1119
1120 if (amount_written != length) {
1121 goto error1;
1122 }
1123 }
1124 data_index = pvar->hosts_state.file_data_index;
1125 } while (1); // ������������
1126
1127 error1:
1128 close_result = _close(fd);
1129 if (amount_written != length || close_result == -1) {
1130 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1131 "An error occurred while trying to write the host key.\n"
1132 "The host key could not be written.");
1133 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1134 goto error2;
1135 }
1136
1137 // �������������t�@�C���������l�[��
1138 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1139 _unlink(buf);
1140 rename(filename, buf);
1141
1142 error2:
1143 _unlink(filename);
1144
1145 finish_read_host_files(pvar, 0);
1146 }
1147 }
1148
1149 //
1150 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1151 // ���[�U���m�F�������B
1152 // TODO: finger print���\�����s���B
1153 // (2006.3.25 yutaka)
1154 //
1155 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1156 LPARAM lParam)
1157 {
1158 PTInstVar pvar;
1159 LOGFONT logfont;
1160 HFONT font;
1161 char uimsg[MAX_UIMSG];
1162
1163 switch (msg) {
1164 case WM_INITDIALOG:
1165 pvar = (PTInstVar) lParam;
1166 pvar->hosts_state.hosts_dialog = dlg;
1167 SetWindowLong(dlg, DWL_USER, lParam);
1168
1169 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1170 GetWindowText(dlg, uimsg, sizeof(uimsg));
1171 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1172 SetWindowText(dlg, pvar->ts->UIMsg);
1173 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1174 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1175 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1176 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1177 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1178 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1179 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1180 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1181 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1182 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1183 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1184 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1185 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1186 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1187 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1188 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1189 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1190 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1191
1192 init_hosts_dlg(pvar, dlg);
1193
1194 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1195 GetObject(font, sizeof(LOGFONT), &logfont);
1196 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1197 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1198 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1199 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1200 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1201 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1202 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1203 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1204 }
1205 else {
1206 DlgHostsAddFont = NULL;
1207 }
1208
1209 // add host check box���`�F�b�N���f�t�H���g������������
1210 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1211
1212 return TRUE; /* because we do not set the focus */
1213
1214 case WM_COMMAND:
1215 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1216
1217 switch (LOWORD(wParam)) {
1218 case IDC_CONTINUE:
1219 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1220 add_host_key(pvar);
1221 }
1222
1223 if (SSHv1(pvar)) {
1224 SSH_notify_host_OK(pvar);
1225 } else { // SSH2
1226 // SSH2���������� SSH_notify_host_OK() �������B
1227 }
1228
1229 pvar->hosts_state.hosts_dialog = NULL;
1230
1231 EndDialog(dlg, 1);
1232
1233 if (DlgHostsAddFont != NULL) {
1234 DeleteObject(DlgHostsAddFont);
1235 }
1236
1237 return TRUE;
1238
1239 case IDCANCEL: /* kill the connection */
1240 pvar->hosts_state.hosts_dialog = NULL;
1241 notify_closed_connection(pvar);
1242 EndDialog(dlg, 0);
1243
1244 if (DlgHostsAddFont != NULL) {
1245 DeleteObject(DlgHostsAddFont);
1246 }
1247
1248 return TRUE;
1249
1250 default:
1251 return FALSE;
1252 }
1253
1254 default:
1255 return FALSE;
1256 }
1257 }
1258
1259 //
1260 // �u�����������m�F�_�C�A���O������
1261 //
1262 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1263 LPARAM lParam)
1264 {
1265 PTInstVar pvar;
1266 LOGFONT logfont;
1267 HFONT font;
1268 char uimsg[MAX_UIMSG];
1269
1270 switch (msg) {
1271 case WM_INITDIALOG:
1272 pvar = (PTInstVar) lParam;
1273 pvar->hosts_state.hosts_dialog = dlg;
1274 SetWindowLong(dlg, DWL_USER, lParam);
1275
1276 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1277 GetWindowText(dlg, uimsg, sizeof(uimsg));
1278 UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1279 SetWindowText(dlg, pvar->ts->UIMsg);
1280 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1281 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1282 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1283 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1284 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1285 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1286 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1287 UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1288 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1289 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1290 UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1291 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1292 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1293 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1294 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1295 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1296 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1297 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1298
1299 init_hosts_dlg(pvar, dlg);
1300
1301 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1302 GetObject(font, sizeof(LOGFONT), &logfont);
1303 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1304 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1305 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1306 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1307 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1308 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1309 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1310 }
1311 else {
1312 DlgHostsReplaceFont = NULL;
1313 }
1314
1315 // �f�t�H���g���`�F�b�N����������
1316 return TRUE; /* because we do not set the focus */
1317
1318 case WM_COMMAND:
1319 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1320
1321 switch (LOWORD(wParam)) {
1322 case IDC_CONTINUE:
1323 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1324 add_host_key(pvar);
1325 delete_different_key(pvar);
1326 }
1327
1328 if (SSHv1(pvar)) {
1329 SSH_notify_host_OK(pvar);
1330 } else { // SSH2
1331 // SSH2���������� SSH_notify_host_OK() �������B
1332 }
1333
1334 pvar->hosts_state.hosts_dialog = NULL;
1335
1336 EndDialog(dlg, 1);
1337
1338 if (DlgHostsReplaceFont != NULL) {
1339 DeleteObject(DlgHostsReplaceFont);
1340 }
1341
1342 return TRUE;
1343
1344 case IDCANCEL: /* kill the connection */
1345 pvar->hosts_state.hosts_dialog = NULL;
1346 notify_closed_connection(pvar);
1347 EndDialog(dlg, 0);
1348
1349 if (DlgHostsReplaceFont != NULL) {
1350 DeleteObject(DlgHostsReplaceFont);
1351 }
1352
1353 return TRUE;
1354
1355 default:
1356 return FALSE;
1357 }
1358
1359 default:
1360 return FALSE;
1361 }
1362 }
1363
1364 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1365 {
1366 if (pvar->hosts_state.hosts_dialog == NULL) {
1367 HWND cur_active = GetActiveWindow();
1368
1369 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1370 cur_active != NULL ? cur_active : wnd,
1371 hosts_add_dlg_proc, (LPARAM) pvar);
1372 }
1373 }
1374
1375 void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1376 {
1377 if (pvar->hosts_state.hosts_dialog == NULL) {
1378 HWND cur_active = GetActiveWindow();
1379
1380 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1381 cur_active != NULL ? cur_active : wnd,
1382 hosts_replace_dlg_proc, (LPARAM) pvar);
1383 }
1384 }
1385
1386 //
1387 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1388 //
1389 // SSH2���������� (2006.3.24 yutaka)
1390 //
1391 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, Key *key)
1392 {
1393 int found_different_key = 0;
1394
1395 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1396 if (pvar->hosts_state.prefetched_hostname != NULL
1397 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1398 && match_key(pvar, key)) {
1399
1400 if (SSHv1(pvar)) {
1401 SSH_notify_host_OK(pvar);
1402 } else {
1403 // SSH2���������� SSH_notify_host_OK() �������B
1404 }
1405 return TRUE;
1406 }
1407
1408 // �������������������������A�������_���t�@�C��������������
1409 if (begin_read_host_files(pvar, 0)) {
1410 do {
1411 if (!read_host_key(pvar, hostname, 0, 0)) {
1412 break;
1413 }
1414
1415 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1416 if (match_key(pvar, key)) {
1417 finish_read_host_files(pvar, 0);
1418 // ���������G���g�����Q�������A���v�����L�[�������������������B
1419 // SSH2���������������������������B(2006.3.29 yutaka)
1420 if (SSHv1(pvar)) {
1421 SSH_notify_host_OK(pvar);
1422 } else {
1423 // SSH2���������� SSH_notify_host_OK() �������B
1424 }
1425 return TRUE;
1426 } else {
1427 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1428 found_different_key = 1;
1429 }
1430 }
1431 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1432
1433 finish_read_host_files(pvar, 0);
1434 }
1435
1436
1437 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1438 pvar->hosts_state.hostkey.type = key->type;
1439 if (key->type == KEY_RSA1) { // SSH1
1440 pvar->hosts_state.hostkey.bits = key->bits;
1441 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1442 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1443
1444 } else if (key->type == KEY_RSA) { // SSH2 RSA
1445 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1446
1447 } else { // SSH2 DSA
1448 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1449
1450 }
1451 free(pvar->hosts_state.prefetched_hostname);
1452 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1453
1454 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1455 // �������K�v�����������A�����R�[�������X�����B
1456 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1457 // (2007.10.1 yutaka)
1458 if (found_different_key) {
1459 #if 0
1460 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1461 ID_SSHDIFFERENTHOST, 0);
1462 #else
1463 HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1464 #endif
1465 } else {
1466 #if 0
1467 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1468 ID_SSHUNKNOWNHOST, 0);
1469 #else
1470 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1471 #endif
1472
1473 }
1474
1475 return TRUE;
1476 }
1477
1478 void HOSTS_notify_disconnecting(PTInstVar pvar)
1479 {
1480 if (pvar->hosts_state.hosts_dialog != NULL) {
1481 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1482 0);
1483 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1484 EnableWindow(pvar->NotificationWindow, TRUE);
1485 }
1486 }
1487
1488 void HOSTS_end(PTInstVar pvar)
1489 {
1490 int i;
1491
1492 free(pvar->hosts_state.prefetched_hostname);
1493 #if 0
1494 free(pvar->hosts_state.key_exp);
1495 free(pvar->hosts_state.key_mod);
1496 #else
1497 init_hostkey(&pvar->hosts_state.hostkey);
1498 #endif
1499
1500 if (pvar->hosts_state.file_names != NULL) {
1501 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1502 free(pvar->hosts_state.file_names[i]);
1503 }
1504 free(pvar->hosts_state.file_names);
1505 }
1506 }

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