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

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