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

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