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 3137 - (show annotations) (download) (as text)
Fri Jul 25 15:48:44 2008 UTC (15 years, 8 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42738 byte(s)
*** empty log message ***

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 unsigned short tcpport, 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 int bracketed;
519 char *end_bracket;
520 int host_matched = 0;
521 unsigned short keyfile_port = 22;
522
523 index++;
524 negated = data[index] == '!';
525
526 if (negated) {
527 index++;
528 bracketed = data[index] == '[';
529 if (bracketed) {
530 end_bracket = strstr(data + index + 1, "]:");
531 if (end_bracket != NULL) {
532 *end_bracket = ' ';
533 index++;
534 }
535 }
536 host_matched = match_pattern(data + index, hostname);
537 if (bracketed && end_bracket != NULL) {
538 *end_bracket = ']';
539 keyfile_port = atoi(end_bracket + 2);
540 }
541 if (host_matched && keyfile_port == tcpport) {
542 return index + eat_to_end_of_line(data + index);
543 }
544 } else {
545 bracketed = data[index] == '[';
546 if (bracketed) {
547 end_bracket = strstr(data + index + 1, "]:");
548 if (end_bracket != NULL) {
549 *end_bracket = ' ';
550 index++;
551 }
552 }
553 host_matched = match_pattern(data + index, hostname);
554 if (bracketed && end_bracket != NULL) {
555 *end_bracket = ']';
556 keyfile_port = atoi(end_bracket + 2);
557 }
558 if (host_matched && keyfile_port == tcpport) {
559 matched = 1;
560 }
561 }
562
563 index += eat_to_end_of_pattern(data + index);
564 } while (data[index] == ',');
565
566 if (!matched) {
567 return index + eat_to_end_of_line(data + index);
568 } else {
569 // ���������������t�H�[�}�b�g��������
570 // �����A���������v�����G���g�����������������������B
571 /*
572 [SSH1]
573 192.168.1.2 1024 35 13032....
574
575 [SSH2]
576 192.168.1.2 ssh-rsa AAAAB3NzaC1....
577 192.168.1.2 ssh-dss AAAAB3NzaC1....
578 192.168.1.2 rsa AAAAB3NzaC1....
579 192.168.1.2 dsa AAAAB3NzaC1....
580 192.168.1.2 rsa1 AAAAB3NzaC1....
581 */
582 int rsa1_key_bits;
583
584 index += eat_spaces(data + index);
585
586 rsa1_key_bits = atoi(data + index);
587 if (rsa1_key_bits > 0) { // RSA1������
588 if (!SSHv1(pvar)) { // SSH2��������������������
589 return index + eat_to_end_of_line(data + index);
590 }
591
592 pvar->hosts_state.hostkey.type = KEY_RSA1;
593
594 pvar->hosts_state.hostkey.bits = rsa1_key_bits;
595 index += eat_digits(data + index);
596 index += eat_spaces(data + index);
597
598 pvar->hosts_state.hostkey.exp = parse_bignum(data + index);
599 index += eat_digits(data + index);
600 index += eat_spaces(data + index);
601
602 pvar->hosts_state.hostkey.mod = parse_bignum(data + index);
603
604 /*
605 if (pvar->hosts_state.key_bits < 0
606 || pvar->hosts_state.key_exp == NULL
607 || pvar->hosts_state.key_mod == NULL) {
608 pvar->hosts_state.key_bits = 0;
609 free(pvar->hosts_state.key_exp);
610 free(pvar->hosts_state.key_mod);
611 }*/
612
613 } else {
614 char *cp, *p;
615 Key *key;
616
617 if (!SSHv2(pvar)) { // SSH1��������������������
618 return index + eat_to_end_of_line(data + index);
619 }
620
621 cp = data + index;
622 p = strchr(cp, ' ');
623 if (p == NULL) {
624 return index + eat_to_end_of_line(data + index);
625 }
626 index += (p - cp); // setup index
627 *p = '\0';
628 pvar->hosts_state.hostkey.type = get_keytype_from_name(cp);
629 *p = ' ';
630
631 index += eat_spaces(data + index); // update index
632
633 // uudecode
634 key = parse_uudecode(data + index);
635 if (key == NULL) {
636 return index + eat_to_end_of_line(data + index);
637 }
638
639 // setup
640 pvar->hosts_state.hostkey.type = key->type;
641 pvar->hosts_state.hostkey.dsa = key->dsa;
642 pvar->hosts_state.hostkey.rsa = key->rsa;
643
644 index += eat_base64(data + index);
645 index += eat_spaces(data + index);
646
647 // Key�\�������g���������� (2008.3.2 yutaka)
648 free(key);
649 }
650
651 return index + eat_to_end_of_line(data + index);
652 }
653 }
654
655 //
656 // known_hosts�t�@�C�������z�X�g�������v�����s������
657 //
658 static int read_host_key(PTInstVar pvar,
659 char FAR * hostname, unsigned short tcpport,
660 int suppress_errors, int return_always)
661 {
662 int i;
663 int while_flg;
664
665 for (i = 0; hostname[i] != 0; i++) {
666 int ch = hostname[i];
667
668 if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
669 if (!suppress_errors) {
670 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
671 "The host name contains an invalid character.\n"
672 "This session will be terminated.");
673 notify_fatal_error(pvar, pvar->ts->UIMsg);
674 }
675 return 0;
676 }
677 }
678
679 if (i == 0) {
680 if (!suppress_errors) {
681 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
682 "The host name should not be empty.\n"
683 "This session will be terminated.");
684 notify_fatal_error(pvar, pvar->ts->UIMsg);
685 }
686 return 0;
687 }
688
689 #if 0
690 pvar->hosts_state.key_bits = 0;
691 free(pvar->hosts_state.key_exp);
692 pvar->hosts_state.key_exp = NULL;
693 free(pvar->hosts_state.key_mod);
694 pvar->hosts_state.key_mod = NULL;
695 #else
696 // hostkey type is KEY_UNSPEC.
697 init_hostkey(&pvar->hosts_state.hostkey);
698 #endif
699
700 do {
701 if (pvar->hosts_state.file_data == NULL
702 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
703 char FAR *filename;
704 int keep_going = 1;
705
706 if (pvar->hosts_state.file_data != NULL) {
707 end_read_file(pvar, suppress_errors);
708 }
709
710 do {
711 filename =
712 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
713
714 if (filename == NULL) {
715 return 1;
716 } else {
717 pvar->hosts_state.file_num++;
718
719 if (filename[0] != 0) {
720 if (begin_read_file(pvar, filename, suppress_errors)) {
721 pvar->hosts_state.file_data_index = 0;
722 keep_going = 0;
723 }
724 }
725 }
726 } while (keep_going);
727 }
728
729 pvar->hosts_state.file_data_index +=
730 check_host_key(pvar, hostname, tcpport,
731 pvar->hosts_state.file_data +
732 pvar->hosts_state.file_data_index);
733
734 if (!return_always) {
735 // �L�����L�[��������������
736 while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
737 }
738 else {
739 while_flg = 0;
740 }
741 } while (while_flg);
742
743 return 1;
744 }
745
746 static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
747 {
748 if (pvar->hosts_state.file_data != NULL) {
749 end_read_file(pvar, suppress_errors);
750 }
751 }
752
753 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
754 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport)
755 {
756 if (!begin_read_host_files(pvar, 1)) {
757 return;
758 }
759
760 if (!read_host_key(pvar, hostname, tcpport, 1, 0)) {
761 return;
762 }
763
764 free(pvar->hosts_state.prefetched_hostname);
765 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
766
767 finish_read_host_files(pvar, 1);
768 }
769
770 static BOOL equal_mp_ints(unsigned char FAR * num1,
771 unsigned char FAR * num2)
772 {
773 if (num1 == NULL || num2 == NULL) {
774 return FALSE;
775 } else {
776 uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
777
778 if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
779 return FALSE; /* different byte lengths */
780 } else {
781 return memcmp(num1 + 2, num2 + 2, bytes) == 0;
782 }
783 }
784 }
785
786 // ���J����������������������
787 static BOOL match_key(PTInstVar pvar, Key *key)
788 {
789 int bits;
790 unsigned char FAR * exp;
791 unsigned char FAR * mod;
792
793 if (key->type == KEY_RSA1) { // SSH1 host public key
794 bits = key->bits;
795 exp = key->exp;
796 mod = key->mod;
797
798 /* just check for equal exponent and modulus */
799 return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
800 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
801 /*
802 return equal_mp_ints(exp, pvar->hosts_state.key_exp)
803 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
804 */
805
806 } else if (key->type == KEY_RSA) { // SSH2 RSA host public key
807
808 return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
809 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
810 BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
811
812 } else { // // SSH2 DSA host public key
813
814 return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
815 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
816 BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
817 BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
818 BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
819
820 }
821
822 }
823
824 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
825 {
826 char buf[1024];
827 char buf2[2048];
828 int i, j;
829 int ch;
830 char *fp = NULL;
831
832 // static text�� # �������z�X�g�����u������
833 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
834 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
835 buf2[i] = ch;
836 }
837 strncpy_s(buf2 + i, sizeof(buf2) - i,
838 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
839 j = i + strlen(buf2 + i);
840 for (; buf[i] == '#'; i++) {
841 }
842 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
843
844 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
845
846 // fingerprint����������
847 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX);
848 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
849 free(fp);
850
851 // �r�W���A����fingerprint���\������
852 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART);
853 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
854 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
855 free(fp);
856 }
857
858 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
859 {
860 int i = 0, j, k;
861 BIGNUM *num = BN_new();
862 int ch;
863
864 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
865
866 do {
867 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
868 i++;
869 } while (!BN_is_zero(num));
870
871 /* we need to reverse the digits */
872 for (j = 0, k = i - 1; j < k; j++, k--) {
873 ch = buf[j];
874 buf[j] = buf[k];
875 buf[k] = ch;
876 }
877
878 buf[i] = 0;
879 return i;
880 }
881
882 //
883 // known_hosts �t�@�C�������������G���g�������������B
884 //
885 static char FAR *format_host_key(PTInstVar pvar)
886 {
887 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
888 char *result = NULL;
889 int index;
890 enum hostkey_type type = pvar->hosts_state.hostkey.type;
891
892 if (type == KEY_RSA1) {
893 int result_len = host_len + 50 + 8 +
894 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
895 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
896 result = (char FAR *) malloc(result_len);
897
898 if (pvar->ssh_state.tcpport == 22) {
899 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
900 index = host_len;
901 }
902 else {
903 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
904 pvar->hosts_state.prefetched_hostname,
905 pvar->ssh_state.tcpport);
906 index = strlen(result);
907 }
908
909 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
910 " %d ", pvar->hosts_state.hostkey.bits);
911 index += strlen(result + index);
912 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
913 result[index] = ' ';
914 index++;
915 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
916 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
917
918 } else if (type == KEY_RSA || type == KEY_DSA) {
919 Key *key = &pvar->hosts_state.hostkey;
920 char *blob = NULL;
921 int blen, uulen, msize;
922 char *uu = NULL;
923 int n;
924
925 key_to_blob(key, &blob, &blen);
926 uulen = 2 * blen;
927 uu = malloc(uulen);
928 if (uu == NULL) {
929 goto error;
930 }
931 n = uuencode(blob, blen, uu, uulen);
932 if (n > 0) {
933 msize = host_len + 50 + uulen;
934 result = malloc(msize);
935 if (result == NULL) {
936 goto error;
937 }
938
939 // setup
940 if (pvar->ssh_state.tcpport == 22) {
941 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
942 pvar->hosts_state.prefetched_hostname,
943 get_sshname_from_key(key),
944 uu);
945 } else {
946 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
947 pvar->hosts_state.prefetched_hostname,
948 pvar->ssh_state.tcpport,
949 get_sshname_from_key(key),
950 uu);
951 }
952 }
953 error:
954 if (blob != NULL)
955 free(blob);
956 if (uu != NULL)
957 free(uu);
958
959 } else {
960 return NULL;
961
962 }
963
964 return result;
965 }
966
967 static void add_host_key(PTInstVar pvar)
968 {
969 char FAR *name = pvar->hosts_state.file_names[0];
970
971 if (name == NULL || name[0] == 0) {
972 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
973 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
974 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
975 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
976 } else {
977 char FAR *keydata = format_host_key(pvar);
978 int length = strlen(keydata);
979 int fd;
980 int amount_written;
981 int close_result;
982 char buf[FILENAME_MAX];
983
984 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
985 fd = _open(buf,
986 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
987 _S_IREAD | _S_IWRITE);
988 if (fd == -1) {
989 if (errno == EACCES) {
990 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
991 "An error occurred while trying to write the host key.\n"
992 "You do not have permission to write to the known-hosts file.");
993 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
994 } else {
995 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
996 "An error occurred while trying to write the host key.\n"
997 "The host key could not be written.");
998 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
999 }
1000 return;
1001 }
1002
1003 amount_written = _write(fd, keydata, length);
1004 free(keydata);
1005 close_result = _close(fd);
1006
1007 if (amount_written != length || close_result == -1) {
1008 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1009 "An error occurred while trying to write the host key.\n"
1010 "The host key could not be written.");
1011 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1012 }
1013 }
1014 }
1015
1016 static char FAR *copy_mp_int(char FAR * num)
1017 {
1018 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1019 char FAR *result = (char FAR *) malloc(len);
1020
1021 if (result != NULL) {
1022 memcpy(result, num, len);
1023 }
1024
1025 return result;
1026 }
1027
1028 //
1029 // �����z�X�g�����e���������L�[����������
1030 // add_host_key ����������������
1031 //
1032 static void delete_different_key(PTInstVar pvar)
1033 {
1034 char FAR *name = pvar->hosts_state.file_names[0];
1035
1036 if (name == NULL || name[0] == 0) {
1037 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1038 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1039 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1040 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1041 }
1042 else {
1043 Key key; // ���������z�X�g���L�[
1044 int length;
1045 char filename[L_tmpnam];
1046 int fd;
1047 int amount_written = 0;
1048 int close_result;
1049 int data_index = 0;
1050 char buf[FILENAME_MAX];
1051
1052 // �������������t�@�C�����J��
1053 tmpnam(filename);
1054 fd = _open(filename,
1055 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1056 _S_IREAD | _S_IWRITE);
1057
1058 if (fd == -1) {
1059 if (errno == EACCES) {
1060 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1061 "An error occurred while trying to write the host key.\n"
1062 "You do not have permission to write to the known-hosts file.");
1063 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1064 } else {
1065 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1066 "An error occurred while trying to write the host key.\n"
1067 "The host key could not be written.");
1068 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1069 }
1070 free(filename);
1071 return;
1072 }
1073
1074 // ���������T�[�o���L�[����������
1075 if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1076 key.type = KEY_RSA1;
1077 key.bits = pvar->hosts_state.hostkey.bits;
1078 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1079 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1080 } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1081 key.type = KEY_RSA;
1082 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1083 } else { // SSH2 DSA
1084 key.type = KEY_DSA;
1085 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1086 }
1087
1088 // �t�@�C��������������
1089 begin_read_host_files(pvar, 0);
1090 do {
1091 int host_index = 0;
1092 int matched = 0;
1093 int keybits = 0;
1094 char FAR *data;
1095 int do_write = 0;
1096 length = amount_written = 0;
1097
1098 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1099 break;
1100 }
1101
1102 if (data_index == pvar->hosts_state.file_data_index) {
1103 // index ���i������ == ��������������
1104 break;
1105 }
1106
1107 data = pvar->hosts_state.file_data + data_index;
1108 host_index = eat_spaces(data);
1109
1110 if (data[host_index] == '#') {
1111 do_write = 1;
1112 }
1113 else {
1114 // �z�X�g������
1115 host_index--;
1116 do {
1117 int negated;
1118 int bracketed;
1119 char *end_bracket;
1120 int host_matched = 0;
1121 unsigned short keyfile_port = 22;
1122
1123 host_index++;
1124 negated = data[host_index] == '!';
1125
1126 if (negated) {
1127 host_index++;
1128 bracketed = data[host_index] == '[';
1129 if (bracketed) {
1130 end_bracket = strstr(data + host_index + 1, "]:");
1131 if (end_bracket != NULL) {
1132 *end_bracket = ' ';
1133 host_index++;
1134 }
1135 }
1136 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1137 if (bracketed && end_bracket != NULL) {
1138 *end_bracket = ']';
1139 keyfile_port = atoi(end_bracket + 2);
1140 }
1141 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1142 matched = 0;
1143 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1144 host_index--;
1145 do {
1146 host_index++;
1147 host_index += eat_to_end_of_pattern(data + host_index);
1148 } while (data[host_index] == ',');
1149 break;
1150 }
1151 }
1152 else {
1153 bracketed = data[host_index] == '[';
1154 if (bracketed) {
1155 end_bracket = strstr(data + host_index + 1, "]:");
1156 if (end_bracket != NULL) {
1157 *end_bracket = ' ';
1158 host_index++;
1159 }
1160 }
1161 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1162 if (bracketed && end_bracket != NULL) {
1163 *end_bracket = ']';
1164 keyfile_port = atoi(end_bracket + 2);
1165 }
1166 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1167 matched = 1;
1168 }
1169 }
1170 host_index += eat_to_end_of_pattern(data + host_index);
1171 } while (data[host_index] == ',');
1172
1173 // �z�X�g�������������v�����L�[����������
1174 if (match_key(pvar, &key)) {
1175 do_write = 1;
1176 }
1177 // �z�X�g������������
1178 else if (!matched) {
1179 do_write = 1;
1180 }
1181 // �z�X�g�������� and �������o�[�W����������
1182 else {
1183 int rsa1_key_bits=0;
1184 rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1185
1186 if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1187 if (!SSHv1(pvar)) {
1188 do_write = 1;
1189 }
1190 }
1191 else { // �t�@�C�����L�[�� ssh2
1192 if (!SSHv2(pvar)) {
1193 do_write = 1;
1194 }
1195 }
1196 }
1197 }
1198
1199 // ������������
1200 if (do_write) {
1201 length = pvar->hosts_state.file_data_index - data_index;
1202 amount_written =
1203 _write(fd, pvar->hosts_state.file_data + data_index,
1204 length);
1205
1206 if (amount_written != length) {
1207 goto error1;
1208 }
1209 }
1210 data_index = pvar->hosts_state.file_data_index;
1211 } while (1); // ������������
1212
1213 error1:
1214 close_result = _close(fd);
1215 if (amount_written != length || close_result == -1) {
1216 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1217 "An error occurred while trying to write the host key.\n"
1218 "The host key could not be written.");
1219 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1220 goto error2;
1221 }
1222
1223 // �������������t�@�C���������l�[��
1224 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1225 _unlink(buf);
1226 rename(filename, buf);
1227
1228 error2:
1229 _unlink(filename);
1230
1231 finish_read_host_files(pvar, 0);
1232 }
1233 }
1234
1235 //
1236 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1237 // ���[�U���m�F�������B
1238 // TODO: finger print���\�����s���B
1239 // (2006.3.25 yutaka)
1240 //
1241 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1242 LPARAM lParam)
1243 {
1244 PTInstVar pvar;
1245 LOGFONT logfont;
1246 HFONT font;
1247 char uimsg[MAX_UIMSG];
1248
1249 switch (msg) {
1250 case WM_INITDIALOG:
1251 pvar = (PTInstVar) lParam;
1252 pvar->hosts_state.hosts_dialog = dlg;
1253 SetWindowLong(dlg, DWL_USER, lParam);
1254
1255 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1256 GetWindowText(dlg, uimsg, sizeof(uimsg));
1257 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1258 SetWindowText(dlg, pvar->ts->UIMsg);
1259 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1260 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1261 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1262 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1263 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1264 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1265 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1266 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1267 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1268 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1269 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1270 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1271 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1272 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1273 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1274 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1275 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1276 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1277
1278 init_hosts_dlg(pvar, dlg);
1279
1280 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1281 GetObject(font, sizeof(LOGFONT), &logfont);
1282 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1283 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1284 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1285 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1286 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1287 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1288 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1289 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1290 }
1291 else {
1292 DlgHostsAddFont = NULL;
1293 }
1294
1295 // add host check box���`�F�b�N���f�t�H���g������������
1296 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1297
1298 return TRUE; /* because we do not set the focus */
1299
1300 case WM_COMMAND:
1301 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1302
1303 switch (LOWORD(wParam)) {
1304 case IDC_CONTINUE:
1305 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1306 add_host_key(pvar);
1307 }
1308
1309 if (SSHv1(pvar)) {
1310 SSH_notify_host_OK(pvar);
1311 } else { // SSH2
1312 // SSH2���������� SSH_notify_host_OK() �������B
1313 }
1314
1315 pvar->hosts_state.hosts_dialog = NULL;
1316
1317 EndDialog(dlg, 1);
1318
1319 if (DlgHostsAddFont != NULL) {
1320 DeleteObject(DlgHostsAddFont);
1321 }
1322
1323 return TRUE;
1324
1325 case IDCANCEL: /* kill the connection */
1326 pvar->hosts_state.hosts_dialog = NULL;
1327 notify_closed_connection(pvar);
1328 EndDialog(dlg, 0);
1329
1330 if (DlgHostsAddFont != NULL) {
1331 DeleteObject(DlgHostsAddFont);
1332 }
1333
1334 return TRUE;
1335
1336 default:
1337 return FALSE;
1338 }
1339
1340 default:
1341 return FALSE;
1342 }
1343 }
1344
1345 //
1346 // �u�����������m�F�_�C�A���O������
1347 //
1348 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1349 LPARAM lParam)
1350 {
1351 PTInstVar pvar;
1352 LOGFONT logfont;
1353 HFONT font;
1354 char uimsg[MAX_UIMSG];
1355
1356 switch (msg) {
1357 case WM_INITDIALOG:
1358 pvar = (PTInstVar) lParam;
1359 pvar->hosts_state.hosts_dialog = dlg;
1360 SetWindowLong(dlg, DWL_USER, lParam);
1361
1362 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1363 GetWindowText(dlg, uimsg, sizeof(uimsg));
1364 UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1365 SetWindowText(dlg, pvar->ts->UIMsg);
1366 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1367 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1368 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1369 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1370 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1371 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1372 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1373 UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1374 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1375 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1376 UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1377 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1378 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1379 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1380 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1381 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1382 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1383 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1384
1385 init_hosts_dlg(pvar, dlg);
1386
1387 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1388 GetObject(font, sizeof(LOGFONT), &logfont);
1389 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1390 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1391 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1392 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1393 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1394 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1395 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1396 }
1397 else {
1398 DlgHostsReplaceFont = NULL;
1399 }
1400
1401 // �f�t�H���g���`�F�b�N����������
1402 return TRUE; /* because we do not set the focus */
1403
1404 case WM_COMMAND:
1405 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1406
1407 switch (LOWORD(wParam)) {
1408 case IDC_CONTINUE:
1409 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1410 add_host_key(pvar);
1411 delete_different_key(pvar);
1412 }
1413
1414 if (SSHv1(pvar)) {
1415 SSH_notify_host_OK(pvar);
1416 } else { // SSH2
1417 // SSH2���������� SSH_notify_host_OK() �������B
1418 }
1419
1420 pvar->hosts_state.hosts_dialog = NULL;
1421
1422 EndDialog(dlg, 1);
1423
1424 if (DlgHostsReplaceFont != NULL) {
1425 DeleteObject(DlgHostsReplaceFont);
1426 }
1427
1428 return TRUE;
1429
1430 case IDCANCEL: /* kill the connection */
1431 pvar->hosts_state.hosts_dialog = NULL;
1432 notify_closed_connection(pvar);
1433 EndDialog(dlg, 0);
1434
1435 if (DlgHostsReplaceFont != NULL) {
1436 DeleteObject(DlgHostsReplaceFont);
1437 }
1438
1439 return TRUE;
1440
1441 default:
1442 return FALSE;
1443 }
1444
1445 default:
1446 return FALSE;
1447 }
1448 }
1449
1450 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1451 {
1452 if (pvar->hosts_state.hosts_dialog == NULL) {
1453 HWND cur_active = GetActiveWindow();
1454
1455 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1456 cur_active != NULL ? cur_active : wnd,
1457 hosts_add_dlg_proc, (LPARAM) pvar);
1458 }
1459 }
1460
1461 void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1462 {
1463 if (pvar->hosts_state.hosts_dialog == NULL) {
1464 HWND cur_active = GetActiveWindow();
1465
1466 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1467 cur_active != NULL ? cur_active : wnd,
1468 hosts_replace_dlg_proc, (LPARAM) pvar);
1469 }
1470 }
1471
1472 //
1473 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1474 //
1475 // SSH2���������� (2006.3.24 yutaka)
1476 //
1477 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1478 {
1479 int found_different_key = 0;
1480
1481 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1482 if (pvar->hosts_state.prefetched_hostname != NULL
1483 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1484 && match_key(pvar, key)) {
1485
1486 if (SSHv1(pvar)) {
1487 SSH_notify_host_OK(pvar);
1488 } else {
1489 // SSH2���������� SSH_notify_host_OK() �������B
1490 }
1491 return TRUE;
1492 }
1493
1494 // �������������������������A�������_���t�@�C��������������
1495 if (begin_read_host_files(pvar, 0)) {
1496 do {
1497 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1498 break;
1499 }
1500
1501 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1502 if (match_key(pvar, key)) {
1503 finish_read_host_files(pvar, 0);
1504 // ���������G���g�����Q�������A���v�����L�[�������������������B
1505 // SSH2���������������������������B(2006.3.29 yutaka)
1506 if (SSHv1(pvar)) {
1507 SSH_notify_host_OK(pvar);
1508 } else {
1509 // SSH2���������� SSH_notify_host_OK() �������B
1510 }
1511 return TRUE;
1512 } else {
1513 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1514 found_different_key = 1;
1515 }
1516 }
1517 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1518
1519 finish_read_host_files(pvar, 0);
1520 }
1521
1522
1523 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1524 pvar->hosts_state.hostkey.type = key->type;
1525 if (key->type == KEY_RSA1) { // SSH1
1526 pvar->hosts_state.hostkey.bits = key->bits;
1527 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1528 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1529
1530 } else if (key->type == KEY_RSA) { // SSH2 RSA
1531 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1532
1533 } else { // SSH2 DSA
1534 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1535
1536 }
1537 free(pvar->hosts_state.prefetched_hostname);
1538 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1539
1540 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1541 // �������K�v�����������A�����R�[�������X�����B
1542 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1543 // (2007.10.1 yutaka)
1544 if (found_different_key) {
1545 #if 0
1546 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1547 ID_SSHDIFFERENTHOST, 0);
1548 #else
1549 HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1550 #endif
1551 } else {
1552 #if 0
1553 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1554 ID_SSHUNKNOWNHOST, 0);
1555 #else
1556 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1557 #endif
1558
1559 }
1560
1561 return TRUE;
1562 }
1563
1564 void HOSTS_notify_disconnecting(PTInstVar pvar)
1565 {
1566 if (pvar->hosts_state.hosts_dialog != NULL) {
1567 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1568 0);
1569 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1570 EnableWindow(pvar->NotificationWindow, TRUE);
1571 }
1572 }
1573
1574 void HOSTS_end(PTInstVar pvar)
1575 {
1576 int i;
1577
1578 free(pvar->hosts_state.prefetched_hostname);
1579 #if 0
1580 free(pvar->hosts_state.key_exp);
1581 free(pvar->hosts_state.key_mod);
1582 #else
1583 init_hostkey(&pvar->hosts_state.hostkey);
1584 #endif
1585
1586 if (pvar->hosts_state.file_names != NULL) {
1587 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1588 free(pvar->hosts_state.file_names[i]);
1589 }
1590 free(pvar->hosts_state.file_names);
1591 }
1592 }

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