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

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