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 4307 - (show annotations) (download) (as text)
Tue Feb 15 09:00:01 2011 UTC (13 years, 1 month ago) by maya
File MIME type: text/x-csrc
File size: 44742 byte(s)
鍵の種類を増やせるように整理した
  enum hostkey_type を ssh_keytype にリネームした
機能が重複している構造体・コードを削除した
  CRYPTKeyPair を削除、Key を使うようにした
  key_from_blob を使うようにした
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
646 index += eat_base64(data + index);
647 index += eat_spaces(data + index);
648
649 // Key�\�������g���������� (2008.3.2 yutaka)
650 free(key);
651 }
652
653 return index + eat_to_end_of_line(data + index);
654 }
655 }
656
657 //
658 // known_hosts�t�@�C�������z�X�g�������v�����s������
659 //
660 static int read_host_key(PTInstVar pvar,
661 char FAR * hostname, unsigned short tcpport,
662 int suppress_errors, int return_always)
663 {
664 int i;
665 int while_flg;
666
667 for (i = 0; hostname[i] != 0; i++) {
668 int ch = hostname[i];
669
670 if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
671 if (!suppress_errors) {
672 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
673 "The host name contains an invalid character.\n"
674 "This session will be terminated.");
675 notify_fatal_error(pvar, pvar->ts->UIMsg);
676 }
677 return 0;
678 }
679 }
680
681 if (i == 0) {
682 if (!suppress_errors) {
683 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
684 "The host name should not be empty.\n"
685 "This session will be terminated.");
686 notify_fatal_error(pvar, pvar->ts->UIMsg);
687 }
688 return 0;
689 }
690
691 #if 0
692 pvar->hosts_state.key_bits = 0;
693 free(pvar->hosts_state.key_exp);
694 pvar->hosts_state.key_exp = NULL;
695 free(pvar->hosts_state.key_mod);
696 pvar->hosts_state.key_mod = NULL;
697 #else
698 // hostkey type is KEY_UNSPEC.
699 init_hostkey(&pvar->hosts_state.hostkey);
700 #endif
701
702 do {
703 if (pvar->hosts_state.file_data == NULL
704 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
705 char FAR *filename;
706 int keep_going = 1;
707
708 if (pvar->hosts_state.file_data != NULL) {
709 end_read_file(pvar, suppress_errors);
710 }
711
712 do {
713 filename =
714 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
715
716 if (filename == NULL) {
717 return 1;
718 } else {
719 pvar->hosts_state.file_num++;
720
721 if (filename[0] != 0) {
722 if (begin_read_file(pvar, filename, suppress_errors)) {
723 pvar->hosts_state.file_data_index = 0;
724 keep_going = 0;
725 }
726 }
727 }
728 } while (keep_going);
729 }
730
731 pvar->hosts_state.file_data_index +=
732 check_host_key(pvar, hostname, tcpport,
733 pvar->hosts_state.file_data +
734 pvar->hosts_state.file_data_index);
735
736 if (!return_always) {
737 // �L�����L�[��������������
738 while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
739 }
740 else {
741 while_flg = 0;
742 }
743 } while (while_flg);
744
745 return 1;
746 }
747
748 static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
749 {
750 if (pvar->hosts_state.file_data != NULL) {
751 end_read_file(pvar, suppress_errors);
752 }
753 }
754
755 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
756 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport)
757 {
758 if (!begin_read_host_files(pvar, 1)) {
759 return;
760 }
761
762 if (!read_host_key(pvar, hostname, tcpport, 1, 0)) {
763 return;
764 }
765
766 free(pvar->hosts_state.prefetched_hostname);
767 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
768
769 finish_read_host_files(pvar, 1);
770 }
771
772 static BOOL equal_mp_ints(unsigned char FAR * num1,
773 unsigned char FAR * num2)
774 {
775 if (num1 == NULL || num2 == NULL) {
776 return FALSE;
777 } else {
778 uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
779
780 if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
781 return FALSE; /* different byte lengths */
782 } else {
783 return memcmp(num1 + 2, num2 + 2, bytes) == 0;
784 }
785 }
786 }
787
788 // ���J����������������������
789 static BOOL match_key(PTInstVar pvar, Key *key)
790 {
791 int bits;
792 unsigned char FAR * exp;
793 unsigned char FAR * mod;
794
795 if (key->type == KEY_RSA1) { // SSH1 host public key
796 bits = key->bits;
797 exp = key->exp;
798 mod = key->mod;
799
800 /* just check for equal exponent and modulus */
801 return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
802 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
803 /*
804 return equal_mp_ints(exp, pvar->hosts_state.key_exp)
805 && equal_mp_ints(mod, pvar->hosts_state.key_mod);
806 */
807
808 } else if (key->type == KEY_RSA) { // SSH2 RSA host public key
809
810 return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
811 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
812 BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
813
814 } else if (key->type == KEY_DSA) { // SSH2 DSA host public key
815
816 return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
817 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
818 BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
819 BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
820 BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
821
822 }
823 else {
824 return FALSE;
825 }
826
827 }
828
829 static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
830 {
831 char buf[1024];
832 char buf2[2048];
833 int i, j;
834 int ch;
835 char *fp = NULL;
836
837 // static text�� # �������z�X�g�����u������
838 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
839 for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
840 buf2[i] = ch;
841 }
842 strncpy_s(buf2 + i, sizeof(buf2) - i,
843 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
844 j = i + strlen(buf2 + i);
845 for (; buf[i] == '#'; i++) {
846 }
847 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
848
849 SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
850
851 // fingerprint����������
852 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX);
853 SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
854 free(fp);
855
856 // �r�W���A����fingerprint���\������
857 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART);
858 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
859 SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
860 free(fp);
861 }
862
863 static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
864 {
865 int i = 0, j, k;
866 BIGNUM *num = BN_new();
867 int ch;
868
869 BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
870
871 do {
872 buf[i] = (char) ((BN_div_word(num, 10)) + '0');
873 i++;
874 } while (!BN_is_zero(num));
875
876 /* we need to reverse the digits */
877 for (j = 0, k = i - 1; j < k; j++, k--) {
878 ch = buf[j];
879 buf[j] = buf[k];
880 buf[k] = ch;
881 }
882
883 buf[i] = 0;
884 return i;
885 }
886
887 //
888 // known_hosts �t�@�C�������������G���g�������������B
889 //
890 static char FAR *format_host_key(PTInstVar pvar)
891 {
892 int host_len = strlen(pvar->hosts_state.prefetched_hostname);
893 char *result = NULL;
894 int index;
895 enum ssh_keytype type = pvar->hosts_state.hostkey.type;
896
897 if (type == KEY_RSA1) {
898 int result_len = host_len + 50 + 8 +
899 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
900 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
901 result = (char FAR *) malloc(result_len);
902
903 if (pvar->ssh_state.tcpport == 22) {
904 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
905 index = host_len;
906 }
907 else {
908 _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
909 pvar->hosts_state.prefetched_hostname,
910 pvar->ssh_state.tcpport);
911 index = strlen(result);
912 }
913
914 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
915 " %d ", pvar->hosts_state.hostkey.bits);
916 index += strlen(result + index);
917 index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
918 result[index] = ' ';
919 index++;
920 index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
921 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
922
923 } else if (type == KEY_RSA || type == KEY_DSA) {
924 Key *key = &pvar->hosts_state.hostkey;
925 char *blob = NULL;
926 int blen, uulen, msize;
927 char *uu = NULL;
928 int n;
929
930 key_to_blob(key, &blob, &blen);
931 uulen = 2 * blen;
932 uu = malloc(uulen);
933 if (uu == NULL) {
934 goto error;
935 }
936 n = uuencode(blob, blen, uu, uulen);
937 if (n > 0) {
938 msize = host_len + 50 + uulen;
939 result = malloc(msize);
940 if (result == NULL) {
941 goto error;
942 }
943
944 // setup
945 if (pvar->ssh_state.tcpport == 22) {
946 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
947 pvar->hosts_state.prefetched_hostname,
948 get_sshname_from_key(key),
949 uu);
950 } else {
951 _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
952 pvar->hosts_state.prefetched_hostname,
953 pvar->ssh_state.tcpport,
954 get_sshname_from_key(key),
955 uu);
956 }
957 }
958 error:
959 if (blob != NULL)
960 free(blob);
961 if (uu != NULL)
962 free(uu);
963
964 } else {
965 return NULL;
966
967 }
968
969 return result;
970 }
971
972 static void add_host_key(PTInstVar pvar)
973 {
974 char FAR *name = NULL;
975
976 if ( pvar->hosts_state.file_names != NULL)
977 name = pvar->hosts_state.file_names[0];
978
979 if (name == NULL || name[0] == 0) {
980 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
981 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
982 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
983 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
984 } else {
985 char FAR *keydata = format_host_key(pvar);
986 int length = strlen(keydata);
987 int fd;
988 int amount_written;
989 int close_result;
990 char buf[FILENAME_MAX];
991
992 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
993 fd = _open(buf,
994 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
995 _S_IREAD | _S_IWRITE);
996 if (fd == -1) {
997 if (errno == EACCES) {
998 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
999 "An error occurred while trying to write the host key.\n"
1000 "You do not have permission to write to the known-hosts file.");
1001 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1002 } else {
1003 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1004 "An error occurred while trying to write the host key.\n"
1005 "The host key could not be written.");
1006 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1007 }
1008 return;
1009 }
1010
1011 amount_written = _write(fd, keydata, length);
1012 free(keydata);
1013 close_result = _close(fd);
1014
1015 if (amount_written != length || close_result == -1) {
1016 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1017 "An error occurred while trying to write the host key.\n"
1018 "The host key could not be written.");
1019 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1020 }
1021 }
1022 }
1023
1024 static char FAR *copy_mp_int(char FAR * num)
1025 {
1026 int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1027 char FAR *result = (char FAR *) malloc(len);
1028
1029 if (result != NULL) {
1030 memcpy(result, num, len);
1031 }
1032
1033 return result;
1034 }
1035
1036 //
1037 // �����z�X�g�����e���������L�[����������
1038 // add_host_key ����������������
1039 //
1040 static void delete_different_key(PTInstVar pvar)
1041 {
1042 char FAR *name = pvar->hosts_state.file_names[0];
1043
1044 if (name == NULL || name[0] == 0) {
1045 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1046 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1047 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1048 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1049 }
1050 else {
1051 Key key; // ���������z�X�g���L�[
1052 int length;
1053 char filename[MAX_PATH];
1054 char tmp[L_tmpnam];
1055 int fd;
1056 int amount_written = 0;
1057 int close_result;
1058 int data_index = 0;
1059 char buf[FILENAME_MAX];
1060
1061 // �������������t�@�C�����J��
1062 _getcwd(filename, sizeof(filename));
1063 tmpnam_s(tmp,sizeof(tmp));
1064 strcat_s(filename, sizeof(filename), tmp);
1065 fd = _open(filename,
1066 _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1067 _S_IREAD | _S_IWRITE);
1068
1069 if (fd == -1) {
1070 if (errno == EACCES) {
1071 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1072 "An error occurred while trying to write the host key.\n"
1073 "You do not have permission to write to the known-hosts file.");
1074 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1075 } else {
1076 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1077 "An error occurred while trying to write the host key.\n"
1078 "The host key could not be written.");
1079 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1080 }
1081 return;
1082 }
1083
1084 // ���������T�[�o���L�[����������
1085 if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1086 key.type = KEY_RSA1;
1087 key.bits = pvar->hosts_state.hostkey.bits;
1088 key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1089 key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1090 } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1091 key.type = KEY_RSA;
1092 key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1093 } else { // SSH2 DSA
1094 key.type = KEY_DSA;
1095 key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1096 }
1097
1098 // �t�@�C��������������
1099 begin_read_host_files(pvar, 0);
1100 do {
1101 int host_index = 0;
1102 int matched = 0;
1103 int keybits = 0;
1104 char FAR *data;
1105 int do_write = 0;
1106 length = amount_written = 0;
1107
1108 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1109 break;
1110 }
1111
1112 if (data_index == pvar->hosts_state.file_data_index) {
1113 // index ���i������ == ��������������
1114 break;
1115 }
1116
1117 data = pvar->hosts_state.file_data + data_index;
1118 host_index = eat_spaces(data);
1119
1120 if (data[host_index] == '#') {
1121 do_write = 1;
1122 }
1123 else {
1124 // �z�X�g������
1125 host_index--;
1126 do {
1127 int negated;
1128 int bracketed;
1129 char *end_bracket;
1130 int host_matched = 0;
1131 unsigned short keyfile_port = 22;
1132
1133 host_index++;
1134 negated = data[host_index] == '!';
1135
1136 if (negated) {
1137 host_index++;
1138 bracketed = data[host_index] == '[';
1139 if (bracketed) {
1140 end_bracket = strstr(data + host_index + 1, "]:");
1141 if (end_bracket != NULL) {
1142 *end_bracket = ' ';
1143 host_index++;
1144 }
1145 }
1146 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1147 if (bracketed && end_bracket != NULL) {
1148 *end_bracket = ']';
1149 keyfile_port = atoi(end_bracket + 2);
1150 }
1151 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1152 matched = 0;
1153 // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1154 host_index--;
1155 do {
1156 host_index++;
1157 host_index += eat_to_end_of_pattern(data + host_index);
1158 } while (data[host_index] == ',');
1159 break;
1160 }
1161 }
1162 else {
1163 bracketed = data[host_index] == '[';
1164 if (bracketed) {
1165 end_bracket = strstr(data + host_index + 1, "]:");
1166 if (end_bracket != NULL) {
1167 *end_bracket = ' ';
1168 host_index++;
1169 }
1170 }
1171 host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1172 if (bracketed && end_bracket != NULL) {
1173 *end_bracket = ']';
1174 keyfile_port = atoi(end_bracket + 2);
1175 }
1176 if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1177 matched = 1;
1178 }
1179 }
1180 host_index += eat_to_end_of_pattern(data + host_index);
1181 } while (data[host_index] == ',');
1182
1183 // �z�X�g�������������v�����L�[����������
1184 if (match_key(pvar, &key)) {
1185 do_write = 1;
1186 }
1187 // �z�X�g������������
1188 else if (!matched) {
1189 do_write = 1;
1190 }
1191 // �z�X�g�������� and �������o�[�W����������
1192 else {
1193 int rsa1_key_bits=0;
1194 rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1195
1196 if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1197 if (!SSHv1(pvar)) {
1198 do_write = 1;
1199 }
1200 }
1201 else { // �t�@�C�����L�[�� ssh2
1202 if (!SSHv2(pvar)) {
1203 do_write = 1;
1204 }
1205 }
1206 }
1207 }
1208
1209 // ������������
1210 if (do_write) {
1211 length = pvar->hosts_state.file_data_index - data_index;
1212 amount_written =
1213 _write(fd, pvar->hosts_state.file_data + data_index,
1214 length);
1215
1216 if (amount_written != length) {
1217 goto error1;
1218 }
1219 }
1220 data_index = pvar->hosts_state.file_data_index;
1221 } while (1); // ������������
1222
1223 error1:
1224 close_result = _close(fd);
1225 if (amount_written != length || close_result == -1) {
1226 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1227 "An error occurred while trying to write the host key.\n"
1228 "The host key could not be written.");
1229 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1230 goto error2;
1231 }
1232
1233 // �������������t�@�C���������l�[��
1234 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1235 _unlink(buf);
1236 rename(filename, buf);
1237
1238 error2:
1239 _unlink(filename);
1240
1241 finish_read_host_files(pvar, 0);
1242 }
1243 }
1244
1245 //
1246 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1247 // ���[�U���m�F�������B
1248 // TODO: finger print���\�����s���B
1249 // (2006.3.25 yutaka)
1250 //
1251 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1252 LPARAM lParam)
1253 {
1254 PTInstVar pvar;
1255 LOGFONT logfont;
1256 HFONT font;
1257 char uimsg[MAX_UIMSG];
1258
1259 switch (msg) {
1260 case WM_INITDIALOG:
1261 pvar = (PTInstVar) lParam;
1262 pvar->hosts_state.hosts_dialog = dlg;
1263 SetWindowLong(dlg, DWL_USER, lParam);
1264
1265 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1266 GetWindowText(dlg, uimsg, sizeof(uimsg));
1267 UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1268 SetWindowText(dlg, pvar->ts->UIMsg);
1269 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1270 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1271 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1272 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1273 UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1274 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1275 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1276 UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1277 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1278 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1279 UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1280 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1281 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1282 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1283 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1284 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1285 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1286 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1287
1288 init_hosts_dlg(pvar, dlg);
1289
1290 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1291 GetObject(font, sizeof(LOGFONT), &logfont);
1292 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1293 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1294 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1295 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1296 SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1297 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1298 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1299 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1300 }
1301 else {
1302 DlgHostsAddFont = NULL;
1303 }
1304
1305 // add host check box���`�F�b�N���f�t�H���g������������
1306 SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1307
1308 return TRUE; /* because we do not set the focus */
1309
1310 case WM_COMMAND:
1311 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1312
1313 switch (LOWORD(wParam)) {
1314 case IDC_CONTINUE:
1315 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1316 add_host_key(pvar);
1317 }
1318
1319 if (SSHv1(pvar)) {
1320 SSH_notify_host_OK(pvar);
1321 } else { // SSH2
1322 // SSH2���������� SSH_notify_host_OK() �������B
1323 }
1324
1325 pvar->hosts_state.hosts_dialog = NULL;
1326
1327 EndDialog(dlg, 1);
1328
1329 if (DlgHostsAddFont != NULL) {
1330 DeleteObject(DlgHostsAddFont);
1331 }
1332
1333 return TRUE;
1334
1335 case IDCANCEL: /* kill the connection */
1336 pvar->hosts_state.hosts_dialog = NULL;
1337 notify_closed_connection(pvar);
1338 EndDialog(dlg, 0);
1339
1340 if (DlgHostsAddFont != NULL) {
1341 DeleteObject(DlgHostsAddFont);
1342 }
1343
1344 return TRUE;
1345
1346 default:
1347 return FALSE;
1348 }
1349
1350 default:
1351 return FALSE;
1352 }
1353 }
1354
1355 //
1356 // �u�����������m�F�_�C�A���O������
1357 //
1358 static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1359 LPARAM lParam)
1360 {
1361 PTInstVar pvar;
1362 LOGFONT logfont;
1363 HFONT font;
1364 char uimsg[MAX_UIMSG];
1365
1366 switch (msg) {
1367 case WM_INITDIALOG:
1368 pvar = (PTInstVar) lParam;
1369 pvar->hosts_state.hosts_dialog = dlg;
1370 SetWindowLong(dlg, DWL_USER, lParam);
1371
1372 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1373 GetWindowText(dlg, uimsg, sizeof(uimsg));
1374 UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1375 SetWindowText(dlg, pvar->ts->UIMsg);
1376 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1377 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1378 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1379 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1380 UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1381 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1382 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1383 UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1384 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1385 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1386 UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1387 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1388 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1389 UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1390 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1391 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1392 UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1393 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1394
1395 init_hosts_dlg(pvar, dlg);
1396
1397 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1398 GetObject(font, sizeof(LOGFONT), &logfont);
1399 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1400 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1401 SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1402 SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1403 SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1404 SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1405 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1406 }
1407 else {
1408 DlgHostsReplaceFont = NULL;
1409 }
1410
1411 // �f�t�H���g���`�F�b�N����������
1412 return TRUE; /* because we do not set the focus */
1413
1414 case WM_COMMAND:
1415 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1416
1417 switch (LOWORD(wParam)) {
1418 case IDC_CONTINUE:
1419 if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1420 add_host_key(pvar);
1421 delete_different_key(pvar);
1422 }
1423
1424 if (SSHv1(pvar)) {
1425 SSH_notify_host_OK(pvar);
1426 } else { // SSH2
1427 // SSH2���������� SSH_notify_host_OK() �������B
1428 }
1429
1430 pvar->hosts_state.hosts_dialog = NULL;
1431
1432 EndDialog(dlg, 1);
1433
1434 if (DlgHostsReplaceFont != NULL) {
1435 DeleteObject(DlgHostsReplaceFont);
1436 }
1437
1438 return TRUE;
1439
1440 case IDCANCEL: /* kill the connection */
1441 pvar->hosts_state.hosts_dialog = NULL;
1442 notify_closed_connection(pvar);
1443 EndDialog(dlg, 0);
1444
1445 if (DlgHostsReplaceFont != NULL) {
1446 DeleteObject(DlgHostsReplaceFont);
1447 }
1448
1449 return TRUE;
1450
1451 default:
1452 return FALSE;
1453 }
1454
1455 default:
1456 return FALSE;
1457 }
1458 }
1459
1460 void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1461 {
1462 if (pvar->hosts_state.hosts_dialog == NULL) {
1463 HWND cur_active = GetActiveWindow();
1464
1465 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1466 cur_active != NULL ? cur_active : wnd,
1467 hosts_add_dlg_proc, (LPARAM) pvar);
1468 }
1469 }
1470
1471 void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1472 {
1473 if (pvar->hosts_state.hosts_dialog == NULL) {
1474 HWND cur_active = GetActiveWindow();
1475
1476 DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1477 cur_active != NULL ? cur_active : wnd,
1478 hosts_replace_dlg_proc, (LPARAM) pvar);
1479 }
1480 }
1481
1482 //
1483 // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1484 //
1485 // SSH2���������� (2006.3.24 yutaka)
1486 //
1487 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1488 {
1489 int found_different_key = 0;
1490
1491 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1492 if (pvar->hosts_state.prefetched_hostname != NULL
1493 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1494 && match_key(pvar, key)) {
1495
1496 if (SSHv1(pvar)) {
1497 SSH_notify_host_OK(pvar);
1498 } else {
1499 // SSH2���������� SSH_notify_host_OK() �������B
1500 }
1501 return TRUE;
1502 }
1503
1504 // �������������������������A�������_���t�@�C��������������
1505 if (begin_read_host_files(pvar, 0)) {
1506 do {
1507 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1508 break;
1509 }
1510
1511 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1512 if (match_key(pvar, key)) {
1513 finish_read_host_files(pvar, 0);
1514 // ���������G���g�����Q�������A���v�����L�[�������������������B
1515 // SSH2���������������������������B(2006.3.29 yutaka)
1516 if (SSHv1(pvar)) {
1517 SSH_notify_host_OK(pvar);
1518 } else {
1519 // SSH2���������� SSH_notify_host_OK() �������B
1520 }
1521 return TRUE;
1522 } else {
1523 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1524 found_different_key = 1;
1525 }
1526 }
1527 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1528
1529 finish_read_host_files(pvar, 0);
1530 }
1531
1532
1533 // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1534 pvar->hosts_state.hostkey.type = key->type;
1535 if (key->type == KEY_RSA1) { // SSH1
1536 pvar->hosts_state.hostkey.bits = key->bits;
1537 pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1538 pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1539
1540 } else if (key->type == KEY_RSA) { // SSH2 RSA
1541 pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1542
1543 } else { // SSH2 DSA
1544 pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1545
1546 }
1547 free(pvar->hosts_state.prefetched_hostname);
1548 pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1549
1550 // "/nosecuritywarning"���w�����������������A�_�C�A���O���\���������� return success �����B
1551 if (pvar->nocheck_known_hosts == TRUE) {
1552 return TRUE;
1553 }
1554
1555 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1556 // �������K�v�����������A�����R�[�������X�����B
1557 // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1558 // (2007.10.1 yutaka)
1559 if (found_different_key) {
1560 #if 0
1561 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1562 ID_SSHDIFFERENTHOST, 0);
1563 #else
1564 HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1565 #endif
1566 } else {
1567 #if 0
1568 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1569 ID_SSHUNKNOWNHOST, 0);
1570 #else
1571 HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1572 #endif
1573
1574 }
1575
1576 return TRUE;
1577 }
1578
1579 void HOSTS_notify_disconnecting(PTInstVar pvar)
1580 {
1581 if (pvar->hosts_state.hosts_dialog != NULL) {
1582 PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1583 0);
1584 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1585 EnableWindow(pvar->NotificationWindow, TRUE);
1586 }
1587 }
1588
1589 void HOSTS_end(PTInstVar pvar)
1590 {
1591 int i;
1592
1593 free(pvar->hosts_state.prefetched_hostname);
1594 #if 0
1595 free(pvar->hosts_state.key_exp);
1596 free(pvar->hosts_state.key_mod);
1597 #else
1598 init_hostkey(&pvar->hosts_state.hostkey);
1599 #endif
1600
1601 if (pvar->hosts_state.file_names != NULL) {
1602 for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1603 free(pvar->hosts_state.file_names[i]);
1604 }
1605 free(pvar->hosts_state.file_names);
1606 }
1607 }

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