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 3126 - (show annotations) (download) (as text)
Mon May 19 08:37:18 2008 UTC (15 years, 10 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 40118 byte(s)
known_hosts のポート番号サポートの下準備

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

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