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 3143 - (show annotations) (download) (as text)
Mon Sep 1 05:13:11 2008 UTC (15 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42719 byte(s)
http://sourceforge.jp/tracker/index.php?func=detail&aid=13353&group_id=1412&atid=5333
tmpnam で受け取ったファイル名は free してはいけないらしい。
notify_nonfatal_error が出ない問題はこの修正で回避される。

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 return;
1071 }
1072
1073 // ���������T�[�o���L�[����������
1074 if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1075 key.type = KEY_RSA1;
1076 key.bits = pvar->hosts_state.hostkey.bits;
1077 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1078 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1079 } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1080 key.type = KEY_RSA;
1081 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1082 } else { // SSH2 DSA
1083 key.type = KEY_DSA;
1084 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1085 }
1086
1087 // �t�@�C��������������
1088 begin_read_host_files(pvar, 0);
1089 do {
1090 int host_index = 0;
1091 int matched = 0;
1092 int keybits = 0;
1093 char FAR *data;
1094 int do_write = 0;
1095 length = amount_written = 0;
1096
1097 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1098 break;
1099 }
1100
1101 if (data_index == pvar->hosts_state.file_data_index) {
1102 // index ���i������ == ��������������
1103 break;
1104 }
1105
1106 data = pvar->hosts_state.file_data + data_index;
1107 host_index = eat_spaces(data);
1108
1109 if (data[host_index] == '#') {
1110 do_write = 1;
1111 }
1112 else {
1113 // �z�X�g������
1114 host_index--;
1115 do {
1116 int negated;
1117 int bracketed;
1118 char *end_bracket;
1119 int host_matched = 0;
1120 unsigned short keyfile_port = 22;
1121
1122 host_index++;
1123 negated = data[host_index] == '!';
1124
1125 if (negated) {
1126 host_index++;
1127 bracketed = data[host_index] == '[';
1128 if (bracketed) {
1129 end_bracket = strstr(data + host_index + 1, "]:");
1130 if (end_bracket != NULL) {
1131 *end_bracket = ' ';
1132 host_index++;
1133 }
1134 }
1135 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1136 if (bracketed && end_bracket != NULL) {
1137 *end_bracket = ']';
1138 keyfile_port = atoi(end_bracket + 2);
1139 }
1140 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1141 matched = 0;
1142 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1143 host_index--;
1144 do {
1145 host_index++;
1146 host_index += eat_to_end_of_pattern(data + host_index);
1147 } while (data[host_index] == ',');
1148 break;
1149 }
1150 }
1151 else {
1152 bracketed = data[host_index] == '[';
1153 if (bracketed) {
1154 end_bracket = strstr(data + host_index + 1, "]:");
1155 if (end_bracket != NULL) {
1156 *end_bracket = ' ';
1157 host_index++;
1158 }
1159 }
1160 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1161 if (bracketed && end_bracket != NULL) {
1162 *end_bracket = ']';
1163 keyfile_port = atoi(end_bracket + 2);
1164 }
1165 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1166 matched = 1;
1167 }
1168 }
1169 host_index += eat_to_end_of_pattern(data + host_index);
1170 } while (data[host_index] == ',');
1171
1172 // �z�X�g�������������v�����L�[����������
1173 if (match_key(pvar, &key)) {
1174 do_write = 1;
1175 }
1176 // �z�X�g������������
1177 else if (!matched) {
1178 do_write = 1;
1179 }
1180 // �z�X�g�������� and �������o�[�W����������
1181 else {
1182 int rsa1_key_bits=0;
1183 rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1184
1185 if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1186 if (!SSHv1(pvar)) {
1187 do_write = 1;
1188 }
1189 }
1190 else { // �t�@�C�����L�[�� ssh2
1191 if (!SSHv2(pvar)) {
1192 do_write = 1;
1193 }
1194 }
1195 }
1196 }
1197
1198 // ������������
1199 if (do_write) {
1200 length = pvar->hosts_state.file_data_index - data_index;
1201 amount_written =
1202 _write(fd, pvar->hosts_state.file_data + data_index,
1203 length);
1204
1205 if (amount_written != length) {
1206 goto error1;
1207 }
1208 }
1209 data_index = pvar->hosts_state.file_data_index;
1210 } while (1); // ������������
1211
1212 error1:
1213 close_result = _close(fd);
1214 if (amount_written != length || close_result == -1) {
1215 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1216 "An error occurred while trying to write the host key.\n"
1217 "The host key could not be written.");
1218 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1219 goto error2;
1220 }
1221
1222 // �������������t�@�C���������l�[��
1223 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1224 _unlink(buf);
1225 rename(filename, buf);
1226
1227 error2:
1228 _unlink(filename);
1229
1230 finish_read_host_files(pvar, 0);
1231 }
1232 }
1233
1234 //
1235 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1236 // ���[�U���m�F�������B
1237 // TODO: finger print���\�����s���B
1238 // (2006.3.25 yutaka)
1239 //
1240 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1241 LPARAM lParam)
1242 {
1243 PTInstVar pvar;
1244 LOGFONT logfont;
1245 HFONT font;
1246 char uimsg[MAX_UIMSG];
1247
1248 switch (msg) {
1249 case WM_INITDIALOG:
1250 pvar = (PTInstVar) lParam;
1251 pvar->hosts_state.hosts_dialog = dlg;
1252 SetWindowLong(dlg, DWL_USER, lParam);
1253
1254 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1255 GetWindowText(dlg, uimsg, sizeof(uimsg));
1256 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1257 SetWindowText(dlg, pvar->ts->UIMsg);
1258 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1259 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1260 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1261 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1262 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1263 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1264 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1265 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1266 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1267 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1268 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1269 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1270 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1271 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1272 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1273 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1274 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1275 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1276
1277 init_hosts_dlg(pvar, dlg);
1278
1279 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1280 GetObject(font, sizeof(LOGFONT), &logfont);
1281 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1282 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1283 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1284 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1285 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1286 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1287 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1288 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1289 }
1290 else {
1291 DlgHostsAddFont = NULL;
1292 }
1293
1294 // add host check box���`�F�b�N���f�t�H���g������������
1295 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1296
1297 return TRUE; /* because we do not set the focus */
1298
1299 case WM_COMMAND:
1300 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1301
1302 switch (LOWORD(wParam)) {
1303 case IDC_CONTINUE:
1304 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1305 add_host_key(pvar);
1306 }
1307
1308 if (SSHv1(pvar)) {
1309 SSH_notify_host_OK(pvar);
1310 } else { // SSH2
1311 // SSH2���������� SSH_notify_host_OK() �������B
1312 }
1313
1314 pvar->hosts_state.hosts_dialog = NULL;
1315
1316 EndDialog(dlg, 1);
1317
1318 if (DlgHostsAddFont != NULL) {
1319 DeleteObject(DlgHostsAddFont);
1320 }
1321
1322 return TRUE;
1323
1324 case IDCANCEL: /* kill the connection */
1325 pvar->hosts_state.hosts_dialog = NULL;
1326 notify_closed_connection(pvar);
1327 EndDialog(dlg, 0);
1328
1329 if (DlgHostsAddFont != NULL) {
1330 DeleteObject(DlgHostsAddFont);
1331 }
1332
1333 return TRUE;
1334
1335 default:
1336 return FALSE;
1337 }
1338
1339 default:
1340 return FALSE;
1341 }
1342 }
1343
1344 //
1345 // �u�����������m�F�_�C�A���O������
1346 //
1347 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1348 LPARAM lParam)
1349 {
1350 PTInstVar pvar;
1351 LOGFONT logfont;
1352 HFONT font;
1353 char uimsg[MAX_UIMSG];
1354
1355 switch (msg) {
1356 case WM_INITDIALOG:
1357 pvar = (PTInstVar) lParam;
1358 pvar->hosts_state.hosts_dialog = dlg;
1359 SetWindowLong(dlg, DWL_USER, lParam);
1360
1361 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1362 GetWindowText(dlg, uimsg, sizeof(uimsg));
1363 UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1364 SetWindowText(dlg, pvar->ts->UIMsg);
1365 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1366 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1367 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1368 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1369 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1370 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1371 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1372 UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1373 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1374 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1375 UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1376 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1377 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1378 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1379 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1380 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1381 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1382 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1383
1384 init_hosts_dlg(pvar, dlg);
1385
1386 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1387 GetObject(font, sizeof(LOGFONT), &logfont);
1388 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1389 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1390 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1391 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1392 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1393 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1394 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1395 }
1396 else {
1397 DlgHostsReplaceFont = NULL;
1398 }
1399
1400 // �f�t�H���g���`�F�b�N����������
1401 return TRUE; /* because we do not set the focus */
1402
1403 case WM_COMMAND:
1404 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1405
1406 switch (LOWORD(wParam)) {
1407 case IDC_CONTINUE:
1408 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1409 add_host_key(pvar);
1410 delete_different_key(pvar);
1411 }
1412
1413 if (SSHv1(pvar)) {
1414 SSH_notify_host_OK(pvar);
1415 } else { // SSH2
1416 // SSH2���������� SSH_notify_host_OK() �������B
1417 }
1418
1419 pvar->hosts_state.hosts_dialog = NULL;
1420
1421 EndDialog(dlg, 1);
1422
1423 if (DlgHostsReplaceFont != NULL) {
1424 DeleteObject(DlgHostsReplaceFont);
1425 }
1426
1427 return TRUE;
1428
1429 case IDCANCEL: /* kill the connection */
1430 pvar->hosts_state.hosts_dialog = NULL;
1431 notify_closed_connection(pvar);
1432 EndDialog(dlg, 0);
1433
1434 if (DlgHostsReplaceFont != NULL) {
1435 DeleteObject(DlgHostsReplaceFont);
1436 }
1437
1438 return TRUE;
1439
1440 default:
1441 return FALSE;
1442 }
1443
1444 default:
1445 return FALSE;
1446 }
1447 }
1448
1449 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1450 {
1451 if (pvar->hosts_state.hosts_dialog == NULL) {
1452 HWND cur_active = GetActiveWindow();
1453
1454 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1455 cur_active != NULL ? cur_active : wnd,
1456 hosts_add_dlg_proc, (LPARAM) pvar);
1457 }
1458 }
1459
1460 void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1461 {
1462 if (pvar->hosts_state.hosts_dialog == NULL) {
1463 HWND cur_active = GetActiveWindow();
1464
1465 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1466 cur_active != NULL ? cur_active : wnd,
1467 hosts_replace_dlg_proc, (LPARAM) pvar);
1468 }
1469 }
1470
1471 //
1472 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1473 //
1474 // SSH2���������� (2006.3.24 yutaka)
1475 //
1476 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1477 {
1478 int found_different_key = 0;
1479
1480 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1481 if (pvar->hosts_state.prefetched_hostname != NULL
1482 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1483 && match_key(pvar, key)) {
1484
1485 if (SSHv1(pvar)) {
1486 SSH_notify_host_OK(pvar);
1487 } else {
1488 // SSH2���������� SSH_notify_host_OK() �������B
1489 }
1490 return TRUE;
1491 }
1492
1493 // �������������������������A�������_���t�@�C��������������
1494 if (begin_read_host_files(pvar, 0)) {
1495 do {
1496 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1497 break;
1498 }
1499
1500 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1501 if (match_key(pvar, key)) {
1502 finish_read_host_files(pvar, 0);
1503 // ���������G���g�����Q�������A���v�����L�[�������������������B
1504 // SSH2���������������������������B(2006.3.29 yutaka)
1505 if (SSHv1(pvar)) {
1506 SSH_notify_host_OK(pvar);
1507 } else {
1508 // SSH2���������� SSH_notify_host_OK() �������B
1509 }
1510 return TRUE;
1511 } else {
1512 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1513 found_different_key = 1;
1514 }
1515 }
1516 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1517
1518 finish_read_host_files(pvar, 0);
1519 }
1520
1521
1522 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1523 pvar->hosts_state.hostkey.type = key->type;
1524 if (key->type == KEY_RSA1) { // SSH1
1525 pvar->hosts_state.hostkey.bits = key->bits;
1526 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1527 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1528
1529 } else if (key->type == KEY_RSA) { // SSH2 RSA
1530 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1531
1532 } else { // SSH2 DSA
1533 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1534
1535 }
1536 free(pvar->hosts_state.prefetched_hostname);
1537 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1538
1539 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1540 // �������K�v�����������A�����R�[�������X�����B
1541 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1542 // (2007.10.1 yutaka)
1543 if (found_different_key) {
1544 #if 0
1545 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1546 ID_SSHDIFFERENTHOST, 0);
1547 #else
1548 HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1549 #endif
1550 } else {
1551 #if 0
1552 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1553 ID_SSHUNKNOWNHOST, 0);
1554 #else
1555 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1556 #endif
1557
1558 }
1559
1560 return TRUE;
1561 }
1562
1563 void HOSTS_notify_disconnecting(PTInstVar pvar)
1564 {
1565 if (pvar->hosts_state.hosts_dialog != NULL) {
1566 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1567 0);
1568 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1569 EnableWindow(pvar->NotificationWindow, TRUE);
1570 }
1571 }
1572
1573 void HOSTS_end(PTInstVar pvar)
1574 {
1575 int i;
1576
1577 free(pvar->hosts_state.prefetched_hostname);
1578 #if 0
1579 free(pvar->hosts_state.key_exp);
1580 free(pvar->hosts_state.key_mod);
1581 #else
1582 init_hostkey(&pvar->hosts_state.hostkey);
1583 #endif
1584
1585 if (pvar->hosts_state.file_names != NULL) {
1586 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1587 free(pvar->hosts_state.file_names[i]);
1588 }
1589 free(pvar->hosts_state.file_names);
1590 }
1591 }

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