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 3127 - (show annotations) (download) (as text)
Mon May 19 12:03:55 2008 UTC (15 years, 10 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42403 byte(s)
known_hosts のポート番号をサポートした。

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;
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);
848 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
849 }
850
851 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
852 {
853 int i = 0, j, k;
854 BIGNUM *num = BN_new();
855 int ch;
856
857 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
858
859 do {
860 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
861 i++;
862 } while (!BN_is_zero(num));
863
864 /* we need to reverse the digits */
865 for (j = 0, k = i - 1; j < k; j++, k--) {
866 ch = buf[j];
867 buf[j] = buf[k];
868 buf[k] = ch;
869 }
870
871 buf[i] = 0;
872 return i;
873 }
874
875 //
876 // known_hosts �t�@�C�������������G���g�������������B
877 //
878 static char FAR *format_host_key(PTInstVar pvar)
879 {
880 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
881 char *result = NULL;
882 int index;
883 enum hostkey_type type = pvar->hosts_state.hostkey.type;
884
885 if (type == KEY_RSA1) {
886 int result_len = host_len + 50 + 8 +
887 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
888 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
889 result = (char FAR *) malloc(result_len);
890
891 if (pvar->ssh_state.tcpport == 22) {
892 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
893 index = host_len;
894 }
895 else {
896 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
897 pvar->hosts_state.prefetched_hostname,
898 pvar->ssh_state.tcpport);
899 index = strlen(result);
900 }
901
902 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
903 " %d ", pvar->hosts_state.hostkey.bits);
904 index += strlen(result + index);
905 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
906 result[index] = ' ';
907 index++;
908 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
909 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
910
911 } else if (type == KEY_RSA || type == KEY_DSA) {
912 Key *key = &pvar->hosts_state.hostkey;
913 char *blob = NULL;
914 int blen, uulen, msize;
915 char *uu = NULL;
916 int n;
917
918 key_to_blob(key, &blob, &blen);
919 uulen = 2 * blen;
920 uu = malloc(uulen);
921 if (uu == NULL) {
922 goto error;
923 }
924 n = uuencode(blob, blen, uu, uulen);
925 if (n > 0) {
926 msize = host_len + 50 + uulen;
927 result = malloc(msize);
928 if (result == NULL) {
929 goto error;
930 }
931
932 // setup
933 if (pvar->ssh_state.tcpport == 22) {
934 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
935 pvar->hosts_state.prefetched_hostname,
936 get_sshname_from_key(key),
937 uu);
938 } else {
939 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
940 pvar->hosts_state.prefetched_hostname,
941 pvar->ssh_state.tcpport,
942 get_sshname_from_key(key),
943 uu);
944 }
945 }
946 error:
947 if (blob != NULL)
948 free(blob);
949 if (uu != NULL)
950 free(uu);
951
952 } else {
953 return NULL;
954
955 }
956
957 return result;
958 }
959
960 static void add_host_key(PTInstVar pvar)
961 {
962 char FAR *name = pvar->hosts_state.file_names[0];
963
964 if (name == NULL || name[0] == 0) {
965 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
966 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
967 "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
968 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
969 } else {
970 char FAR *keydata = format_host_key(pvar);
971 int length = strlen(keydata);
972 int fd;
973 int amount_written;
974 int close_result;
975 char buf[FILENAME_MAX];
976
977 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
978 fd = _open(buf,
979 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
980 _S_IREAD | _S_IWRITE);
981 if (fd == -1) {
982 if (errno == EACCES) {
983 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
984 "An error occurred while trying to write the host key.\n"
985 "You do not have permission to write to the known-hosts file.");
986 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
987 } else {
988 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
989 "An error occurred while trying to write the host key.\n"
990 "The host key could not be written.");
991 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
992 }
993 return;
994 }
995
996 amount_written = _write(fd, keydata, length);
997 free(keydata);
998 close_result = _close(fd);
999
1000 if (amount_written != length || close_result == -1) {
1001 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1002 "An error occurred while trying to write the host key.\n"
1003 "The host key could not be written.");
1004 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1005 }
1006 }
1007 }
1008
1009 static char FAR *copy_mp_int(char FAR * num)
1010 {
1011 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1012 char FAR *result = (char FAR *) malloc(len);
1013
1014 if (result != NULL) {
1015 memcpy(result, num, len);
1016 }
1017
1018 return result;
1019 }
1020
1021 //
1022 // �����z�X�g�����e���������L�[����������
1023 // add_host_key ����������������
1024 //
1025 static void delete_different_key(PTInstVar pvar)
1026 {
1027 char FAR *name = pvar->hosts_state.file_names[0];
1028
1029 if (name == NULL || name[0] == 0) {
1030 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1031 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1032 "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1033 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1034 }
1035 else {
1036 Key key; // ���������z�X�g���L�[
1037 int length;
1038 char filename[L_tmpnam];
1039 int fd;
1040 int amount_written = 0;
1041 int close_result;
1042 int data_index = 0;
1043 char buf[FILENAME_MAX];
1044
1045 // �������������t�@�C�����J��
1046 tmpnam(filename);
1047 fd = _open(filename,
1048 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1049 _S_IREAD | _S_IWRITE);
1050
1051 if (fd == -1) {
1052 if (errno == EACCES) {
1053 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1054 "An error occurred while trying to write the host key.\n"
1055 "You do not have permission to write to the known-hosts file.");
1056 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1057 } else {
1058 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1059 "An error occurred while trying to write the host key.\n"
1060 "The host key could not be written.");
1061 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1062 }
1063 free(filename);
1064 return;
1065 }
1066
1067 // ���������T�[�o���L�[����������
1068 if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1069 key.type = KEY_RSA1;
1070 key.bits = pvar->hosts_state.hostkey.bits;
1071 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1072 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1073 } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1074 key.type = KEY_RSA;
1075 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1076 } else { // SSH2 DSA
1077 key.type = KEY_DSA;
1078 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1079 }
1080
1081 // �t�@�C��������������
1082 begin_read_host_files(pvar, 0);
1083 do {
1084 int host_index = 0;
1085 int matched = 0;
1086 int keybits = 0;
1087 char FAR *data;
1088 int do_write = 0;
1089 length = amount_written = 0;
1090
1091 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1092 break;
1093 }
1094
1095 if (data_index == pvar->hosts_state.file_data_index) {
1096 // index ���i������ == ��������������
1097 break;
1098 }
1099
1100 data = pvar->hosts_state.file_data + data_index;
1101 host_index = eat_spaces(data);
1102
1103 if (data[host_index] == '#') {
1104 do_write = 1;
1105 }
1106 else {
1107 // �z�X�g������
1108 host_index--;
1109 do {
1110 int negated;
1111 int bracketed;
1112 char *end_bracket;
1113 int host_matched = 0;
1114 unsigned short keyfile_port = 22;
1115
1116 host_index++;
1117 negated = data[host_index] == '!';
1118
1119 if (negated) {
1120 host_index++;
1121 bracketed = data[host_index] == '[';
1122 if (bracketed) {
1123 end_bracket = strstr(data + host_index + 1, "]:");
1124 if (end_bracket != NULL) {
1125 *end_bracket = ' ';
1126 host_index++;
1127 }
1128 }
1129 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1130 if (bracketed && end_bracket != NULL) {
1131 *end_bracket = ']';
1132 keyfile_port = atoi(end_bracket + 2);
1133 }
1134 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1135 matched = 0;
1136 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1137 host_index--;
1138 do {
1139 host_index++;
1140 host_index += eat_to_end_of_pattern(data + host_index);
1141 } while (data[host_index] == ',');
1142 break;
1143 }
1144 }
1145 else {
1146 bracketed = data[host_index] == '[';
1147 if (bracketed) {
1148 end_bracket = strstr(data + host_index + 1, "]:");
1149 if (end_bracket != NULL) {
1150 *end_bracket = ' ';
1151 host_index++;
1152 }
1153 }
1154 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1155 if (bracketed && end_bracket != NULL) {
1156 *end_bracket = ']';
1157 keyfile_port = atoi(end_bracket + 2);
1158 }
1159 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1160 matched = 1;
1161 }
1162 }
1163 host_index += eat_to_end_of_pattern(data + host_index);
1164 } while (data[host_index] == ',');
1165
1166 // �z�X�g�������������v�����L�[����������
1167 if (match_key(pvar, &key)) {
1168 do_write = 1;
1169 }
1170 // �z�X�g������������
1171 else if (!matched) {
1172 do_write = 1;
1173 }
1174 // �z�X�g�������� and �������o�[�W����������
1175 else {
1176 int rsa1_key_bits=0;
1177 rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1178
1179 if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1180 if (!SSHv1(pvar)) {
1181 do_write = 1;
1182 }
1183 }
1184 else { // �t�@�C�����L�[�� ssh2
1185 if (!SSHv2(pvar)) {
1186 do_write = 1;
1187 }
1188 }
1189 }
1190 }
1191
1192 // ������������
1193 if (do_write) {
1194 length = pvar->hosts_state.file_data_index - data_index;
1195 amount_written =
1196 _write(fd, pvar->hosts_state.file_data + data_index,
1197 length);
1198
1199 if (amount_written != length) {
1200 goto error1;
1201 }
1202 }
1203 data_index = pvar->hosts_state.file_data_index;
1204 } while (1); // ������������
1205
1206 error1:
1207 close_result = _close(fd);
1208 if (amount_written != length || close_result == -1) {
1209 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1210 "An error occurred while trying to write the host key.\n"
1211 "The host key could not be written.");
1212 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1213 goto error2;
1214 }
1215
1216 // �������������t�@�C���������l�[��
1217 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1218 _unlink(buf);
1219 rename(filename, buf);
1220
1221 error2:
1222 _unlink(filename);
1223
1224 finish_read_host_files(pvar, 0);
1225 }
1226 }
1227
1228 //
1229 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1230 // ���[�U���m�F�������B
1231 // TODO: finger print���\�����s���B
1232 // (2006.3.25 yutaka)
1233 //
1234 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1235 LPARAM lParam)
1236 {
1237 PTInstVar pvar;
1238 LOGFONT logfont;
1239 HFONT font;
1240 char uimsg[MAX_UIMSG];
1241
1242 switch (msg) {
1243 case WM_INITDIALOG:
1244 pvar = (PTInstVar) lParam;
1245 pvar->hosts_state.hosts_dialog = dlg;
1246 SetWindowLong(dlg, DWL_USER, lParam);
1247
1248 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1249 GetWindowText(dlg, uimsg, sizeof(uimsg));
1250 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1251 SetWindowText(dlg, pvar->ts->UIMsg);
1252 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1253 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1254 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1255 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1256 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1257 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1258 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1259 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1260 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1261 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1262 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1263 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1264 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1265 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1266 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1267 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1268 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1269 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1270
1271 init_hosts_dlg(pvar, dlg);
1272
1273 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1274 GetObject(font, sizeof(LOGFONT), &logfont);
1275 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1276 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1277 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1278 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1279 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1280 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1281 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1282 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1283 }
1284 else {
1285 DlgHostsAddFont = NULL;
1286 }
1287
1288 // add host check box���`�F�b�N���f�t�H���g������������
1289 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1290
1291 return TRUE; /* because we do not set the focus */
1292
1293 case WM_COMMAND:
1294 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1295
1296 switch (LOWORD(wParam)) {
1297 case IDC_CONTINUE:
1298 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1299 add_host_key(pvar);
1300 }
1301
1302 if (SSHv1(pvar)) {
1303 SSH_notify_host_OK(pvar);
1304 } else { // SSH2
1305 // SSH2���������� SSH_notify_host_OK() �������B
1306 }
1307
1308 pvar->hosts_state.hosts_dialog = NULL;
1309
1310 EndDialog(dlg, 1);
1311
1312 if (DlgHostsAddFont != NULL) {
1313 DeleteObject(DlgHostsAddFont);
1314 }
1315
1316 return TRUE;
1317
1318 case IDCANCEL: /* kill the connection */
1319 pvar->hosts_state.hosts_dialog = NULL;
1320 notify_closed_connection(pvar);
1321 EndDialog(dlg, 0);
1322
1323 if (DlgHostsAddFont != NULL) {
1324 DeleteObject(DlgHostsAddFont);
1325 }
1326
1327 return TRUE;
1328
1329 default:
1330 return FALSE;
1331 }
1332
1333 default:
1334 return FALSE;
1335 }
1336 }
1337
1338 //
1339 // �u�����������m�F�_�C�A���O������
1340 //
1341 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1342 LPARAM lParam)
1343 {
1344 PTInstVar pvar;
1345 LOGFONT logfont;
1346 HFONT font;
1347 char uimsg[MAX_UIMSG];
1348
1349 switch (msg) {
1350 case WM_INITDIALOG:
1351 pvar = (PTInstVar) lParam;
1352 pvar->hosts_state.hosts_dialog = dlg;
1353 SetWindowLong(dlg, DWL_USER, lParam);
1354
1355 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1356 GetWindowText(dlg, uimsg, sizeof(uimsg));
1357 UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1358 SetWindowText(dlg, pvar->ts->UIMsg);
1359 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1360 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1361 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1362 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1363 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1364 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1365 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1366 UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1367 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1368 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1369 UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1370 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1371 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1372 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1373 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1374 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1375 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1376 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1377
1378 init_hosts_dlg(pvar, dlg);
1379
1380 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1381 GetObject(font, sizeof(LOGFONT), &logfont);
1382 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1383 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1384 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1385 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1386 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1387 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1388 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1389 }
1390 else {
1391 DlgHostsReplaceFont = NULL;
1392 }
1393
1394 // �f�t�H���g���`�F�b�N����������
1395 return TRUE; /* because we do not set the focus */
1396
1397 case WM_COMMAND:
1398 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1399
1400 switch (LOWORD(wParam)) {
1401 case IDC_CONTINUE:
1402 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1403 add_host_key(pvar);
1404 delete_different_key(pvar);
1405 }
1406
1407 if (SSHv1(pvar)) {
1408 SSH_notify_host_OK(pvar);
1409 } else { // SSH2
1410 // SSH2���������� SSH_notify_host_OK() �������B
1411 }
1412
1413 pvar->hosts_state.hosts_dialog = NULL;
1414
1415 EndDialog(dlg, 1);
1416
1417 if (DlgHostsReplaceFont != NULL) {
1418 DeleteObject(DlgHostsReplaceFont);
1419 }
1420
1421 return TRUE;
1422
1423 case IDCANCEL: /* kill the connection */
1424 pvar->hosts_state.hosts_dialog = NULL;
1425 notify_closed_connection(pvar);
1426 EndDialog(dlg, 0);
1427
1428 if (DlgHostsReplaceFont != NULL) {
1429 DeleteObject(DlgHostsReplaceFont);
1430 }
1431
1432 return TRUE;
1433
1434 default:
1435 return FALSE;
1436 }
1437
1438 default:
1439 return FALSE;
1440 }
1441 }
1442
1443 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1444 {
1445 if (pvar->hosts_state.hosts_dialog == NULL) {
1446 HWND cur_active = GetActiveWindow();
1447
1448 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1449 cur_active != NULL ? cur_active : wnd,
1450 hosts_add_dlg_proc, (LPARAM) pvar);
1451 }
1452 }
1453
1454 void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1455 {
1456 if (pvar->hosts_state.hosts_dialog == NULL) {
1457 HWND cur_active = GetActiveWindow();
1458
1459 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1460 cur_active != NULL ? cur_active : wnd,
1461 hosts_replace_dlg_proc, (LPARAM) pvar);
1462 }
1463 }
1464
1465 //
1466 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1467 //
1468 // SSH2���������� (2006.3.24 yutaka)
1469 //
1470 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1471 {
1472 int found_different_key = 0;
1473
1474 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1475 if (pvar->hosts_state.prefetched_hostname != NULL
1476 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1477 && match_key(pvar, key)) {
1478
1479 if (SSHv1(pvar)) {
1480 SSH_notify_host_OK(pvar);
1481 } else {
1482 // SSH2���������� SSH_notify_host_OK() �������B
1483 }
1484 return TRUE;
1485 }
1486
1487 // �������������������������A�������_���t�@�C��������������
1488 if (begin_read_host_files(pvar, 0)) {
1489 do {
1490 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1491 break;
1492 }
1493
1494 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1495 if (match_key(pvar, key)) {
1496 finish_read_host_files(pvar, 0);
1497 // ���������G���g�����Q�������A���v�����L�[�������������������B
1498 // SSH2���������������������������B(2006.3.29 yutaka)
1499 if (SSHv1(pvar)) {
1500 SSH_notify_host_OK(pvar);
1501 } else {
1502 // SSH2���������� SSH_notify_host_OK() �������B
1503 }
1504 return TRUE;
1505 } else {
1506 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1507 found_different_key = 1;
1508 }
1509 }
1510 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1511
1512 finish_read_host_files(pvar, 0);
1513 }
1514
1515
1516 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1517 pvar->hosts_state.hostkey.type = key->type;
1518 if (key->type == KEY_RSA1) { // SSH1
1519 pvar->hosts_state.hostkey.bits = key->bits;
1520 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1521 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1522
1523 } else if (key->type == KEY_RSA) { // SSH2 RSA
1524 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1525
1526 } else { // SSH2 DSA
1527 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1528
1529 }
1530 free(pvar->hosts_state.prefetched_hostname);
1531 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1532
1533 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1534 // �������K�v�����������A�����R�[�������X�����B
1535 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1536 // (2007.10.1 yutaka)
1537 if (found_different_key) {
1538 #if 0
1539 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1540 ID_SSHDIFFERENTHOST, 0);
1541 #else
1542 HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1543 #endif
1544 } else {
1545 #if 0
1546 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1547 ID_SSHUNKNOWNHOST, 0);
1548 #else
1549 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1550 #endif
1551
1552 }
1553
1554 return TRUE;
1555 }
1556
1557 void HOSTS_notify_disconnecting(PTInstVar pvar)
1558 {
1559 if (pvar->hosts_state.hosts_dialog != NULL) {
1560 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1561 0);
1562 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1563 EnableWindow(pvar->NotificationWindow, TRUE);
1564 }
1565 }
1566
1567 void HOSTS_end(PTInstVar pvar)
1568 {
1569 int i;
1570
1571 free(pvar->hosts_state.prefetched_hostname);
1572 #if 0
1573 free(pvar->hosts_state.key_exp);
1574 free(pvar->hosts_state.key_mod);
1575 #else
1576 init_hostkey(&pvar->hosts_state.hostkey);
1577 #endif
1578
1579 if (pvar->hosts_state.file_names != NULL) {
1580 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1581 free(pvar->hosts_state.file_names[i]);
1582 }
1583 free(pvar->hosts_state.file_names);
1584 }
1585 }

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