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 3003 - (show annotations) (download) (as text)
Mon Aug 20 14:21:57 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 39475 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
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.file_data_index] == 0) {
667 char FAR *filename;
668 int keep_going = 1;
669
670 if (pvar->hosts_state.file_data != NULL) {
671 end_read_file(pvar, suppress_errors);
672 }
673
674 do {
675 filename =
676 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
677
678 if (filename == NULL) {
679 return 1;
680 } else {
681 pvar->hosts_state.file_num++;
682
683 if (filename[0] != 0) {
684 if (begin_read_file(pvar, filename, suppress_errors)) {
685 pvar->hosts_state.file_data_index = 0;
686 keep_going = 0;
687 }
688 }
689 }
690 } while (keep_going);
691 }
692
693 pvar->hosts_state.file_data_index +=
694 check_host_key(pvar, hostname,
695 pvar->hosts_state.file_data +
696 pvar->hosts_state.file_data_index);
697
698 if (!return_always) {
699 // �L�����L�[��������������
700 while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
701 }
702 else {
703 while_flg = 0;
704 }
705 } while (while_flg);
706
707 return 1;
708 }
709
710 static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
711 {
712 if (pvar->hosts_state.file_data != NULL) {
713 end_read_file(pvar, suppress_errors);
714 }
715 }
716
717 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
718 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname)
719 {
720 if (!begin_read_host_files(pvar, 1)) {
721 return;
722 }
723
724 if (!read_host_key(pvar, hostname, 1, 0)) {
725 return;
726 }
727
728 free(pvar->hosts_state.prefetched_hostname);
729 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
730
731 finish_read_host_files(pvar, 1);
732 }
733
734 static BOOL equal_mp_ints(unsigned char FAR * num1,
735 unsigned char FAR * num2)
736 {
737 if (num1 == NULL || num2 == NULL) {
738 return FALSE;
739 } else {
740 uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
741
742 if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
743 return FALSE; /* different byte lengths */
744 } else {
745 return memcmp(num1 + 2, num2 + 2, bytes) == 0;
746 }
747 }
748 }
749
750 // ���J����������������������
751 static BOOL match_key(PTInstVar pvar, Key *key)
752 {
753 int bits;
754 unsigned char FAR * exp;
755 unsigned char FAR * mod;
756
757 if (key->type == KEY_RSA1) { // SSH1 host public key
758 bits = key->bits;
759 exp = key->exp;
760 mod = key->mod;
761
762 /* just check for equal exponent and modulus */
763 return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
764 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
765 /*
766 return equal_mp_ints(exp, pvar->hosts_state.key_exp)
767 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
768 */
769
770 } else if (key->type == KEY_RSA) { // SSH2 RSA host public key
771
772 return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
773 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
774 BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
775
776 } else { // // SSH2 DSA host public key
777
778 return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
779 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
780 BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
781 BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
782 BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
783
784 }
785
786 }
787
788 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
789 {
790 char buf[1024];
791 char buf2[2048];
792 int i, j;
793 int ch;
794 char *fp;
795
796 // static text�� # �������z�X�g�����u������
797 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
798 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
799 buf2[i] = ch;
800 }
801 strncpy_s(buf2 + i, sizeof(buf2) - i,
802 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
803 j = i + strlen(buf2 + i);
804 for (; buf[i] == '#'; i++) {
805 }
806 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
807
808 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
809
810 // fingerprint����������
811 fp = key_fingerprint(&pvar->hosts_state.hostkey);
812 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
813 }
814
815 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
816 {
817 int i = 0, j, k;
818 BIGNUM *num = BN_new();
819 int ch;
820
821 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
822
823 do {
824 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
825 i++;
826 } while (!BN_is_zero(num));
827
828 /* we need to reverse the digits */
829 for (j = 0, k = i - 1; j < k; j++, k--) {
830 ch = buf[j];
831 buf[j] = buf[k];
832 buf[k] = ch;
833 }
834
835 buf[i] = 0;
836 return i;
837 }
838
839 //
840 // known_hosts �t�@�C�������������G���g�������������B
841 //
842 static char FAR *format_host_key(PTInstVar pvar)
843 {
844 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
845 char *result = NULL;
846 int index;
847 enum hostkey_type type = pvar->hosts_state.hostkey.type;
848
849 if (type == KEY_RSA1) {
850 int result_len = host_len + 50 +
851 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
852 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
853 result = (char FAR *) malloc(result_len);
854
855 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
856 index = host_len;
857
858 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
859 " %d ", pvar->hosts_state.hostkey.bits);
860 index += strlen(result + index);
861 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
862 result[index] = ' ';
863 index++;
864 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
865 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
866
867 } else if (type == KEY_RSA || type == KEY_DSA) {
868 Key *key = &pvar->hosts_state.hostkey;
869 char *blob = NULL;
870 int blen, uulen, msize;
871 char *uu = NULL;
872 int n;
873
874 key_to_blob(key, &blob, &blen);
875 uulen = 2 * blen;
876 uu = malloc(uulen);
877 if (uu == NULL) {
878 goto error;
879 }
880 n = uuencode(blob, blen, uu, uulen);
881 if (n > 0) {
882 msize = host_len + 50 + uulen;
883 result = malloc(msize);
884 if (result == NULL) {
885 goto error;
886 }
887
888 // setup
889 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
890 pvar->hosts_state.prefetched_hostname,
891 get_sshname_from_key(key),
892 uu);
893 }
894 error:
895 if (blob != NULL)
896 free(blob);
897 if (uu != NULL)
898 free(uu);
899
900 } else {
901 return NULL;
902
903 }
904
905 return result;
906 }
907
908 static void add_host_key(PTInstVar pvar)
909 {
910 char FAR *name = pvar->hosts_state.file_names[0];
911
912 if (name == NULL || name[0] == 0) {
913 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
914 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
915 "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
916 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
917 } else {
918 char FAR *keydata = format_host_key(pvar);
919 int length = strlen(keydata);
920 int fd;
921 int amount_written;
922 int close_result;
923 char buf[FILENAME_MAX];
924
925 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
926 fd = _open(buf,
927 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
928 _S_IREAD | _S_IWRITE);
929 if (fd == -1) {
930 if (errno == EACCES) {
931 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
932 "An error occurred while trying to write the host key.\n"
933 "You do not have permission to write to the known-hosts file.");
934 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
935 } else {
936 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
937 "An error occurred while trying to write the host key.\n"
938 "The host key could not be written.");
939 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
940 }
941 return;
942 }
943
944 amount_written = _write(fd, keydata, length);
945 free(keydata);
946 close_result = _close(fd);
947
948 if (amount_written != length || close_result == -1) {
949 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
950 "An error occurred while trying to write the host key.\n"
951 "The host key could not be written.");
952 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
953 }
954 }
955 }
956
957 static char FAR *copy_mp_int(char FAR * num)
958 {
959 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
960 char FAR *result = (char FAR *) malloc(len);
961
962 if (result != NULL) {
963 memcpy(result, num, len);
964 }
965
966 return result;
967 }
968
969 //
970 // �����z�X�g�����e���������L�[����������
971 // add_host_key ����������������
972 //
973 static void delete_different_key(PTInstVar pvar)
974 {
975 char FAR *name = pvar->hosts_state.file_names[0];
976
977 if (name == NULL || name[0] == 0) {
978 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
979 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
980 "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
981 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
982 }
983 else {
984 Key key; // ���������z�X�g���L�[
985 int length;
986 char filename[L_tmpnam];
987 int fd;
988 int amount_written = 0;
989 int close_result;
990 int data_index = 0;
991 char buf[FILENAME_MAX];
992
993 // �������������t�@�C�����J��
994 tmpnam(filename);
995 fd = _open(filename,
996 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
997 _S_IREAD | _S_IWRITE);
998
999 if (fd == -1) {
1000 if (errno == EACCES) {
1001 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1002 "An error occurred while trying to write the host key.\n"
1003 "You do not have permission to write to the known-hosts file.");
1004 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1005 } else {
1006 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1007 "An error occurred while trying to write the host key.\n"
1008 "The host key could not be written.");
1009 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1010 }
1011 free(filename);
1012 return;
1013 }
1014
1015 // ���������T�[�o���L�[����������
1016 if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1017 key.type = KEY_RSA1;
1018 key.bits = pvar->hosts_state.hostkey.bits;
1019 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1020 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1021 } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1022 key.type = KEY_RSA;
1023 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1024 } else { // SSH2 DSA
1025 key.type = KEY_DSA;
1026 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1027 }
1028
1029 // �t�@�C��������������
1030 begin_read_host_files(pvar, 0);
1031 do {
1032 int host_index = 0;
1033 int matched = 0;
1034 int keybits = 0;
1035 char FAR *data;
1036 int do_write = 0;
1037 length = amount_written = 0;
1038
1039 if (!read_host_key(pvar, pvar->ssh_state.hostname, 0, 1)) {
1040 break;
1041 }
1042
1043 if (data_index == pvar->hosts_state.file_data_index) {
1044 // index ���i������ == ��������������
1045 break;
1046 }
1047
1048 data = pvar->hosts_state.file_data + data_index;
1049 host_index = eat_spaces(data);
1050
1051 if (data[host_index] == '#') {
1052 do_write = 1;
1053 }
1054 else {
1055 // �z�X�g������
1056 host_index--;
1057 do {
1058 int negated;
1059
1060 host_index++;
1061 negated = data[host_index] == '!';
1062
1063 if (negated) {
1064 host_index++;
1065 if (match_pattern(data + host_index,
1066 pvar->ssh_state.hostname)) {
1067 matched = 0;
1068 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1069 host_index--;
1070 do {
1071 host_index++;
1072 host_index += eat_to_end_of_pattern(data + host_index);
1073 } while (data[host_index] == ',');
1074 break;
1075 }
1076 }
1077 else if (match_pattern(data + host_index,
1078 pvar->ssh_state.hostname)) {
1079 matched = 1;
1080 }
1081 host_index += eat_to_end_of_pattern(data + host_index);
1082 } while (data[host_index] == ',');
1083
1084 // �z�X�g�������������v�����L�[����������
1085 if (match_key(pvar, &key)) {
1086 do_write = 1;
1087 }
1088 // �z�X�g������������
1089 else if (!matched) {
1090 do_write = 1;
1091 }
1092 // �z�X�g�������� and �������o�[�W����������
1093 else {
1094 int rsa1_key_bits=0;
1095 rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1096
1097 if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1098 if (!SSHv1(pvar)) {
1099 do_write = 1;
1100 }
1101 }
1102 else { // �t�@�C�����L�[�� ssh2
1103 if (!SSHv2(pvar)) {
1104 do_write = 1;
1105 }
1106 }
1107 }
1108 }
1109
1110 // ������������
1111 if (do_write) {
1112 length = pvar->hosts_state.file_data_index - data_index;
1113 amount_written =
1114 _write(fd, pvar->hosts_state.file_data + data_index,
1115 length);
1116
1117 if (amount_written != length) {
1118 goto error1;
1119 }
1120 }
1121 data_index = pvar->hosts_state.file_data_index;
1122 } while (1); // ������������
1123
1124 error1:
1125 close_result = _close(fd);
1126 if (amount_written != length || close_result == -1) {
1127 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1128 "An error occurred while trying to write the host key.\n"
1129 "The host key could not be written.");
1130 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1131 goto error2;
1132 }
1133
1134 // �������������t�@�C���������l�[��
1135 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1136 _unlink(buf);
1137 rename(filename, buf);
1138
1139 error2:
1140 _unlink(filename);
1141
1142 finish_read_host_files(pvar, 0);
1143 }
1144 }
1145
1146 //
1147 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1148 // ���[�U���m�F�������B
1149 // TODO: finger print���\�����s���B
1150 // (2006.3.25 yutaka)
1151 //
1152 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1153 LPARAM lParam)
1154 {
1155 PTInstVar pvar;
1156 LOGFONT logfont;
1157 HFONT font;
1158 char uimsg[MAX_UIMSG];
1159
1160 switch (msg) {
1161 case WM_INITDIALOG:
1162 pvar = (PTInstVar) lParam;
1163 pvar->hosts_state.hosts_dialog = dlg;
1164 SetWindowLong(dlg, DWL_USER, lParam);
1165
1166 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1167 GetWindowText(dlg, uimsg, sizeof(uimsg));
1168 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1169 SetWindowText(dlg, pvar->ts->UIMsg);
1170 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1171 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1172 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1173 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1174 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1175 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1176 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1177 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1178 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1179 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1180 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1181 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1182 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1183 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1184 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1185 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1186 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1187 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1188
1189 init_hosts_dlg(pvar, dlg);
1190
1191 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1192 GetObject(font, sizeof(LOGFONT), &logfont);
1193 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1194 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1195 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1196 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1197 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1198 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1199 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1200 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1201 }
1202 else {
1203 DlgHostsAddFont = NULL;
1204 }
1205
1206 // add host check box���`�F�b�N���f�t�H���g������������
1207 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1208
1209 return TRUE; /* because we do not set the focus */
1210
1211 case WM_COMMAND:
1212 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1213
1214 switch (LOWORD(wParam)) {
1215 case IDC_CONTINUE:
1216 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1217 add_host_key(pvar);
1218 }
1219
1220 if (SSHv1(pvar)) {
1221 SSH_notify_host_OK(pvar);
1222 } else { // SSH2
1223 // SSH2���������� SSH_notify_host_OK() �������B
1224 }
1225
1226 pvar->hosts_state.hosts_dialog = NULL;
1227
1228 EndDialog(dlg, 1);
1229
1230 if (DlgHostsAddFont != NULL) {
1231 DeleteObject(DlgHostsAddFont);
1232 }
1233
1234 return TRUE;
1235
1236 case IDCANCEL: /* kill the connection */
1237 pvar->hosts_state.hosts_dialog = NULL;
1238 notify_closed_connection(pvar);
1239 EndDialog(dlg, 0);
1240
1241 if (DlgHostsAddFont != NULL) {
1242 DeleteObject(DlgHostsAddFont);
1243 }
1244
1245 return TRUE;
1246
1247 default:
1248 return FALSE;
1249 }
1250
1251 default:
1252 return FALSE;
1253 }
1254 }
1255
1256 //
1257 // �u�����������m�F�_�C�A���O������
1258 //
1259 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1260 LPARAM lParam)
1261 {
1262 PTInstVar pvar;
1263 LOGFONT logfont;
1264 HFONT font;
1265 char uimsg[MAX_UIMSG];
1266
1267 switch (msg) {
1268 case WM_INITDIALOG:
1269 pvar = (PTInstVar) lParam;
1270 pvar->hosts_state.hosts_dialog = dlg;
1271 SetWindowLong(dlg, DWL_USER, lParam);
1272
1273 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1274 GetWindowText(dlg, uimsg, sizeof(uimsg));
1275 UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1276 SetWindowText(dlg, pvar->ts->UIMsg);
1277 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1278 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1279 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1280 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1281 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1282 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1283 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1284 UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1285 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1286 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1287 UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1288 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1289 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1290 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1291 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1292 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1293 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1294 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1295
1296 init_hosts_dlg(pvar, dlg);
1297
1298 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1299 GetObject(font, sizeof(LOGFONT), &logfont);
1300 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1301 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1302 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1303 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1304 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1305 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1306 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1307 }
1308 else {
1309 DlgHostsReplaceFont = NULL;
1310 }
1311
1312 // �f�t�H���g���`�F�b�N����������
1313 return TRUE; /* because we do not set the focus */
1314
1315 case WM_COMMAND:
1316 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1317
1318 switch (LOWORD(wParam)) {
1319 case IDC_CONTINUE:
1320 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1321 add_host_key(pvar);
1322 delete_different_key(pvar);
1323 }
1324
1325 if (SSHv1(pvar)) {
1326 SSH_notify_host_OK(pvar);
1327 } else { // SSH2
1328 // SSH2���������� SSH_notify_host_OK() �������B
1329 }
1330
1331 pvar->hosts_state.hosts_dialog = NULL;
1332
1333 EndDialog(dlg, 1);
1334
1335 if (DlgHostsReplaceFont != NULL) {
1336 DeleteObject(DlgHostsReplaceFont);
1337 }
1338
1339 return TRUE;
1340
1341 case IDCANCEL: /* kill the connection */
1342 pvar->hosts_state.hosts_dialog = NULL;
1343 notify_closed_connection(pvar);
1344 EndDialog(dlg, 0);
1345
1346 if (DlgHostsReplaceFont != NULL) {
1347 DeleteObject(DlgHostsReplaceFont);
1348 }
1349
1350 return TRUE;
1351
1352 default:
1353 return FALSE;
1354 }
1355
1356 default:
1357 return FALSE;
1358 }
1359 }
1360
1361 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1362 {
1363 if (pvar->hosts_state.hosts_dialog == NULL) {
1364 HWND cur_active = GetActiveWindow();
1365
1366 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1367 cur_active != NULL ? cur_active : wnd,
1368 hosts_add_dlg_proc, (LPARAM) pvar);
1369 }
1370 }
1371
1372 void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1373 {
1374 if (pvar->hosts_state.hosts_dialog == NULL) {
1375 HWND cur_active = GetActiveWindow();
1376
1377 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1378 cur_active != NULL ? cur_active : wnd,
1379 hosts_replace_dlg_proc, (LPARAM) pvar);
1380 }
1381 }
1382
1383 //
1384 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1385 //
1386 // SSH2���������� (2006.3.24 yutaka)
1387 //
1388 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, Key *key)
1389 {
1390 int found_different_key = 0;
1391
1392 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1393 if (pvar->hosts_state.prefetched_hostname != NULL
1394 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1395 && match_key(pvar, key)) {
1396
1397 if (SSHv1(pvar)) {
1398 SSH_notify_host_OK(pvar);
1399 } else {
1400 // SSH2���������� SSH_notify_host_OK() �������B
1401 }
1402 return TRUE;
1403 }
1404
1405 // �������������������������A�������_���t�@�C��������������
1406 if (begin_read_host_files(pvar, 0)) {
1407 do {
1408 if (!read_host_key(pvar, hostname, 0, 0)) {
1409 break;
1410 }
1411
1412 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1413 if (match_key(pvar, key)) {
1414 finish_read_host_files(pvar, 0);
1415 // ���������G���g�����Q�������A���v�����L�[�������������������B
1416 // SSH2���������������������������B(2006.3.29 yutaka)
1417 if (SSHv1(pvar)) {
1418 SSH_notify_host_OK(pvar);
1419 } else {
1420 // SSH2���������� SSH_notify_host_OK() �������B
1421 }
1422 return TRUE;
1423 } else {
1424 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1425 found_different_key = 1;
1426 }
1427 }
1428 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1429
1430 finish_read_host_files(pvar, 0);
1431 }
1432
1433
1434 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1435 pvar->hosts_state.hostkey.type = key->type;
1436 if (key->type == KEY_RSA1) { // SSH1
1437 pvar->hosts_state.hostkey.bits = key->bits;
1438 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1439 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1440
1441 } else if (key->type == KEY_RSA) { // SSH2 RSA
1442 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1443
1444 } else { // SSH2 DSA
1445 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1446
1447 }
1448 free(pvar->hosts_state.prefetched_hostname);
1449 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1450
1451 if (found_different_key) {
1452 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1453 ID_SSHDIFFERENTHOST, 0);
1454 } else {
1455 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1456 ID_SSHUNKNOWNHOST, 0);
1457 }
1458
1459 return TRUE;
1460 }
1461
1462 void HOSTS_notify_disconnecting(PTInstVar pvar)
1463 {
1464 if (pvar->hosts_state.hosts_dialog != NULL) {
1465 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1466 0);
1467 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1468 EnableWindow(pvar->NotificationWindow, TRUE);
1469 }
1470 }
1471
1472 void HOSTS_end(PTInstVar pvar)
1473 {
1474 int i;
1475
1476 free(pvar->hosts_state.prefetched_hostname);
1477 #if 0
1478 free(pvar->hosts_state.key_exp);
1479 free(pvar->hosts_state.key_mod);
1480 #else
1481 init_hostkey(&pvar->hosts_state.hostkey);
1482 #endif
1483
1484 if (pvar->hosts_state.file_names != NULL) {
1485 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1486 free(pvar->hosts_state.file_names[i]);
1487 }
1488 free(pvar->hosts_state.file_names);
1489 }
1490 }

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