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 3144 - (show annotations) (download) (as text)
Wed Sep 3 17:05:44 2008 UTC (15 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42854 byte(s)
ssh_knwon_hosts の鍵の置換で、一時書き込みファイルをフルパスで開くようにした。
http://sourceforge.jp/tracker/index.php?func=detail&aid=13353&group_id=1412&atid=5333

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

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