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

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