Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/ttssh2/ttxssh/hosts.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3017 - (hide annotations) (download) (as text)
Mon Oct 1 14:03:43 2007 UTC (16 years, 6 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 39882 byte(s)
known_hostsダイアログは同期的に表示させ、この時点においてユーザに確認
させる必要があるため、直接コールに変更する。
これによりknown_hostsの確認を待たずに、サーバへユーザ情報を送ってしまう問題を回避する。

1 yutakakn 2728 /*
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 yutakakn 2856 #include "ssh.h"
39     #include "hosts.h"
40 yutakakn 2728
41     #include <openssl/bn.h>
42 yutakakn 2856 #include <openssl/evp.h>
43     #include <openssl/rsa.h>
44     #include <openssl/dsa.h>
45 yutakakn 2728
46     #include <fcntl.h>
47     #include <io.h>
48     #include <errno.h>
49     #include <sys/stat.h>
50    
51 maya 2943 static HFONT DlgHostsAddFont;
52     static HFONT DlgHostsReplaceFont;
53 yutakakn 2856
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 yutakakn 2728 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 yutakakn 2856 #if 0
126 yutakakn 2728 pvar->hosts_state.key_exp = NULL;
127     pvar->hosts_state.key_mod = NULL;
128 yutakakn 2856 #else
129     init_hostkey(&pvar->hosts_state.hostkey);
130     #endif
131 yutakakn 2728 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 yutakakn 2856 //
142     // known_hosts�t�@�C�������e�������� pvar->hosts_state.file_data ����������
143     //
144 yutakakn 2728 static int begin_read_file(PTInstVar pvar, char FAR * name,
145 maya 3003 int suppress_errors)
146 yutakakn 2728 {
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 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_READ_ENOENT_ERROR", pvar,
158 maya 3003 "An error occurred while trying to read a known_hosts file.\n"
159     "The specified filename does not exist.");
160 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
161 yutakakn 2728 } else {
162 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
163 maya 3003 "An error occurred while trying to read a known_hosts file.");
164 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
165 yutakakn 2728 }
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 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_ALLOC_ERROR", pvar,
178 maya 3003 "Memory ran out while trying to allocate space to read a known_hosts file.");
179 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
180 yutakakn 2728 }
181     _close(fd);
182     return 0;
183     }
184     } else {
185     if (!suppress_errors) {
186 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
187 maya 3003 "An error occurred while trying to read a known_hosts file.");
188 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
189 yutakakn 2728 }
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 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
202 maya 3003 "An error occurred while trying to read a known_hosts file.");
203 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
204 yutakakn 2728 }
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 yutakakn 2856 // 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 yutakakn 2728 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 yutakakn 2856 //
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 yutakakn 2728 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 yutakakn 2856 //
500     // known_hosts�t�@�C�������e���������A�w�������z�X�g�����J�����T���B
501     //
502 yutakakn 2728 static int check_host_key(PTInstVar pvar, char FAR * hostname,
503 maya 3003 char FAR * data)
504 yutakakn 2728 {
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 yutakakn 2856 // ���������������t�H�[�}�b�g��������
538     // �����A���������v�����G���g�����������������������B
539     /*
540     [SSH1]
541     192.168.1.2 1024 35 13032....
542 yutakakn 2728
543 yutakakn 2856 [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 yutakakn 2728
552     index += eat_spaces(data + index);
553    
554 yutakakn 2856 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 yutakakn 2728
560 yutakakn 2856 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 yutakakn 2728 }
615    
616     return index + eat_to_end_of_line(data + index);
617     }
618     }
619    
620 yutakakn 2856 //
621     // known_hosts�t�@�C�������z�X�g�������v�����s������
622     //
623 yutakakn 2728 static int read_host_key(PTInstVar pvar, char FAR * hostname,
624 maya 3003 int suppress_errors, int return_always)
625 yutakakn 2728 {
626     int i;
627 yutakakn 2861 int while_flg;
628 yutakakn 2728
629     for (i = 0; hostname[i] != 0; i++) {
630     int ch = hostname[i];
631    
632     if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
633     if (!suppress_errors) {
634 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
635 maya 3003 "The host name contains an invalid character.\n"
636     "This session will be terminated.");
637 maya 2942 notify_fatal_error(pvar, pvar->ts->UIMsg);
638 yutakakn 2728 }
639     return 0;
640     }
641     }
642    
643     if (i == 0) {
644     if (!suppress_errors) {
645 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
646 maya 3003 "The host name should not be empty.\n"
647     "This session will be terminated.");
648 maya 2942 notify_fatal_error(pvar, pvar->ts->UIMsg);
649 yutakakn 2728 }
650     return 0;
651     }
652    
653 yutakakn 2856 #if 0
654 yutakakn 2728 pvar->hosts_state.key_bits = 0;
655     free(pvar->hosts_state.key_exp);
656     pvar->hosts_state.key_exp = NULL;
657     free(pvar->hosts_state.key_mod);
658     pvar->hosts_state.key_mod = NULL;
659 yutakakn 2856 #else
660     // hostkey type is KEY_UNSPEC.
661     init_hostkey(&pvar->hosts_state.hostkey);
662     #endif
663 yutakakn 2728
664     do {
665     if (pvar->hosts_state.file_data == NULL
666 maya 3003 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
667 yutakakn 2728 char FAR *filename;
668     int keep_going = 1;
669    
670     if (pvar->hosts_state.file_data != NULL) {
671     end_read_file(pvar, suppress_errors);
672     }
673    
674     do {
675     filename =
676 maya 3003 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
677 yutakakn 2728
678     if (filename == NULL) {
679     return 1;
680     } else {
681     pvar->hosts_state.file_num++;
682    
683     if (filename[0] != 0) {
684 maya 3003 if (begin_read_file(pvar, filename, suppress_errors)) {
685 yutakakn 2728 pvar->hosts_state.file_data_index = 0;
686     keep_going = 0;
687     }
688     }
689     }
690     } while (keep_going);
691     }
692    
693     pvar->hosts_state.file_data_index +=
694     check_host_key(pvar, hostname,
695 maya 3003 pvar->hosts_state.file_data +
696     pvar->hosts_state.file_data_index);
697 yutakakn 2728
698 yutakakn 2861 if (!return_always) {
699     // �L�����L�[��������������
700     while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
701     }
702     else {
703     while_flg = 0;
704     }
705     } while (while_flg);
706    
707 yutakakn 2728 return 1;
708     }
709    
710     static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
711     {
712     if (pvar->hosts_state.file_data != NULL) {
713     end_read_file(pvar, suppress_errors);
714     }
715     }
716    
717 yutakakn 2856 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
718 yutakakn 2728 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname)
719     {
720     if (!begin_read_host_files(pvar, 1)) {
721     return;
722     }
723    
724 yutakakn 2861 if (!read_host_key(pvar, hostname, 1, 0)) {
725 yutakakn 2728 return;
726     }
727    
728     free(pvar->hosts_state.prefetched_hostname);
729     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
730    
731     finish_read_host_files(pvar, 1);
732     }
733    
734     static BOOL equal_mp_ints(unsigned char FAR * num1,
735 maya 3003 unsigned char FAR * num2)
736 yutakakn 2728 {
737     if (num1 == NULL || num2 == NULL) {
738     return FALSE;
739     } else {
740     uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
741    
742     if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
743     return FALSE; /* different byte lengths */
744     } else {
745     return memcmp(num1 + 2, num2 + 2, bytes) == 0;
746     }
747     }
748     }
749    
750 yutakakn 2856 // ���J����������������������
751     static BOOL match_key(PTInstVar pvar, Key *key)
752 yutakakn 2728 {
753 yutakakn 2856 int bits;
754     unsigned char FAR * exp;
755     unsigned char FAR * mod;
756    
757     if (key->type == KEY_RSA1) { // SSH1 host public key
758     bits = key->bits;
759     exp = key->exp;
760     mod = key->mod;
761    
762     /* just check for equal exponent and modulus */
763     return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
764 maya 3003 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
765 yutakakn 2856 /*
766     return equal_mp_ints(exp, pvar->hosts_state.key_exp)
767     && equal_mp_ints(mod, pvar->hosts_state.key_mod);
768     */
769    
770     } else if (key->type == KEY_RSA) { // SSH2 RSA host public key
771    
772     return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
773 maya 3003 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
774     BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
775 yutakakn 2856
776     } else { // // SSH2 DSA host public key
777    
778     return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
779 maya 3003 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
780     BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
781     BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
782     BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
783 yutakakn 2856
784     }
785    
786 yutakakn 2728 }
787    
788     static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
789     {
790     char buf[1024];
791     char buf2[2048];
792     int i, j;
793     int ch;
794 yutakakn 2857 char *fp;
795 yutakakn 2728
796 yutakakn 2857 // static text�� # �������z�X�g�����u������
797 yutakakn 2728 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
798     for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
799     buf2[i] = ch;
800     }
801 maya 2992 strncpy_s(buf2 + i, sizeof(buf2) - i,
802 maya 3003 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
803 yutakakn 2728 j = i + strlen(buf2 + i);
804     for (; buf[i] == '#'; i++) {
805     }
806 maya 2992 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
807 yutakakn 2728
808     SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
809 yutakakn 2857
810     // fingerprint����������
811     fp = key_fingerprint(&pvar->hosts_state.hostkey);
812     SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
813 yutakakn 2728 }
814    
815     static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
816     {
817     int i = 0, j, k;
818     BIGNUM *num = BN_new();
819     int ch;
820    
821     BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
822    
823     do {
824     buf[i] = (char) ((BN_div_word(num, 10)) + '0');
825     i++;
826     } while (!BN_is_zero(num));
827    
828     /* we need to reverse the digits */
829     for (j = 0, k = i - 1; j < k; j++, k--) {
830     ch = buf[j];
831     buf[j] = buf[k];
832     buf[k] = ch;
833     }
834    
835     buf[i] = 0;
836     return i;
837     }
838    
839 yutakakn 2856 //
840     // known_hosts �t�@�C�������������G���g�������������B
841     //
842 yutakakn 2728 static char FAR *format_host_key(PTInstVar pvar)
843     {
844     int host_len = strlen(pvar->hosts_state.prefetched_hostname);
845 yutakakn 2856 char *result = NULL;
846     int index;
847     enum hostkey_type type = pvar->hosts_state.hostkey.type;
848    
849     if (type == KEY_RSA1) {
850 maya 2992 int result_len = host_len + 50 +
851 maya 3003 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
852     get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
853 maya 2992 result = (char FAR *) malloc(result_len);
854 yutakakn 2728
855 maya 2992 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
856 yutakakn 2856 index = host_len;
857 yutakakn 2728
858 maya 2992 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
859 maya 3003 " %d ", pvar->hosts_state.hostkey.bits);
860 yutakakn 2856 index += strlen(result + index);
861     index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
862     result[index] = ' ';
863     index++;
864     index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
865 maya 2992 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
866 yutakakn 2728
867 yutakakn 2856 } else if (type == KEY_RSA || type == KEY_DSA) {
868     Key *key = &pvar->hosts_state.hostkey;
869     char *blob = NULL;
870     int blen, uulen, msize;
871     char *uu = NULL;
872     int n;
873    
874     key_to_blob(key, &blob, &blen);
875     uulen = 2 * blen;
876     uu = malloc(uulen);
877     if (uu == NULL) {
878     goto error;
879     }
880     n = uuencode(blob, blen, uu, uulen);
881     if (n > 0) {
882     msize = host_len + 50 + uulen;
883     result = malloc(msize);
884     if (result == NULL) {
885     goto error;
886     }
887    
888     // setup
889 maya 2992 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
890 maya 3003 pvar->hosts_state.prefetched_hostname,
891     get_sshname_from_key(key),
892     uu);
893 yutakakn 2856 }
894     error:
895     if (blob != NULL)
896     free(blob);
897     if (uu != NULL)
898     free(uu);
899    
900     } else {
901     return NULL;
902    
903     }
904    
905 yutakakn 2728 return result;
906     }
907    
908     static void add_host_key(PTInstVar pvar)
909     {
910     char FAR *name = pvar->hosts_state.file_names[0];
911    
912 maya 2879 if (name == NULL || name[0] == 0) {
913 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
914 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
915     "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
916 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
917 yutakakn 2728 } else {
918     char FAR *keydata = format_host_key(pvar);
919     int length = strlen(keydata);
920 maya 2879 int fd;
921 yutakakn 2728 int amount_written;
922     int close_result;
923 maya 2879 char buf[FILENAME_MAX];
924 yutakakn 2728
925 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
926     fd = _open(buf,
927 maya 3003 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
928     _S_IREAD | _S_IWRITE);
929 yutakakn 2728 if (fd == -1) {
930     if (errno == EACCES) {
931 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
932 maya 3003 "An error occurred while trying to write the host key.\n"
933     "You do not have permission to write to the known-hosts file.");
934 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
935 yutakakn 2728 } else {
936 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
937 maya 3003 "An error occurred while trying to write the host key.\n"
938     "The host key could not be written.");
939 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
940 yutakakn 2728 }
941     return;
942     }
943    
944     amount_written = _write(fd, keydata, length);
945     free(keydata);
946     close_result = _close(fd);
947    
948     if (amount_written != length || close_result == -1) {
949 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
950 maya 3003 "An error occurred while trying to write the host key.\n"
951     "The host key could not be written.");
952 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
953 yutakakn 2728 }
954     }
955     }
956    
957 yutakakn 2861 static char FAR *copy_mp_int(char FAR * num)
958     {
959     int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
960     char FAR *result = (char FAR *) malloc(len);
961    
962     if (result != NULL) {
963     memcpy(result, num, len);
964     }
965    
966     return result;
967     }
968    
969 yutakakn 2856 //
970 yutakakn 2861 // �����z�X�g�����e���������L�[����������
971     // add_host_key ����������������
972     //
973     static void delete_different_key(PTInstVar pvar)
974     {
975     char FAR *name = pvar->hosts_state.file_names[0];
976    
977 maya 2879 if (name == NULL || name[0] == 0) {
978 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
979 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
980     "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
981 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
982 yutakakn 2861 }
983     else {
984     Key key; // ���������z�X�g���L�[
985 yutakakn 2876 int length;
986 yutakakn 2861 char filename[L_tmpnam];
987     int fd;
988     int amount_written = 0;
989     int close_result;
990     int data_index = 0;
991 maya 2879 char buf[FILENAME_MAX];
992 yutakakn 2861
993     // �������������t�@�C�����J��
994     tmpnam(filename);
995 maya 3003 fd = _open(filename,
996     _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
997     _S_IREAD | _S_IWRITE);
998 yutakakn 2861
999     if (fd == -1) {
1000     if (errno == EACCES) {
1001 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1002 maya 3003 "An error occurred while trying to write the host key.\n"
1003     "You do not have permission to write to the known-hosts file.");
1004 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1005 yutakakn 2861 } else {
1006 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1007 maya 3003 "An error occurred while trying to write the host key.\n"
1008     "The host key could not be written.");
1009 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1010 yutakakn 2861 }
1011     free(filename);
1012     return;
1013     }
1014    
1015     // ���������T�[�o���L�[����������
1016     if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1017     key.type = KEY_RSA1;
1018     key.bits = pvar->hosts_state.hostkey.bits;
1019     key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1020     key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1021     } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1022     key.type = KEY_RSA;
1023     key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1024     } else { // SSH2 DSA
1025     key.type = KEY_DSA;
1026     key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1027     }
1028    
1029     // �t�@�C��������������
1030     begin_read_host_files(pvar, 0);
1031     do {
1032     int host_index = 0;
1033     int matched = 0;
1034     int keybits = 0;
1035     char FAR *data;
1036     int do_write = 0;
1037     length = amount_written = 0;
1038    
1039     if (!read_host_key(pvar, pvar->ssh_state.hostname, 0, 1)) {
1040     break;
1041     }
1042    
1043     if (data_index == pvar->hosts_state.file_data_index) {
1044     // index ���i������ == ��������������
1045     break;
1046     }
1047    
1048     data = pvar->hosts_state.file_data + data_index;
1049     host_index = eat_spaces(data);
1050    
1051     if (data[host_index] == '#') {
1052     do_write = 1;
1053     }
1054     else {
1055     // �z�X�g������
1056     host_index--;
1057     do {
1058     int negated;
1059    
1060     host_index++;
1061     negated = data[host_index] == '!';
1062    
1063     if (negated) {
1064     host_index++;
1065     if (match_pattern(data + host_index,
1066 maya 3003 pvar->ssh_state.hostname)) {
1067 yutakakn 2861 matched = 0;
1068     // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1069     host_index--;
1070     do {
1071     host_index++;
1072     host_index += eat_to_end_of_pattern(data + host_index);
1073     } while (data[host_index] == ',');
1074     break;
1075     }
1076     }
1077     else if (match_pattern(data + host_index,
1078 maya 3003 pvar->ssh_state.hostname)) {
1079 yutakakn 2861 matched = 1;
1080     }
1081     host_index += eat_to_end_of_pattern(data + host_index);
1082     } while (data[host_index] == ',');
1083    
1084     // �z�X�g�������������v�����L�[����������
1085     if (match_key(pvar, &key)) {
1086     do_write = 1;
1087     }
1088     // �z�X�g������������
1089     else if (!matched) {
1090     do_write = 1;
1091     }
1092     // �z�X�g�������� and �������o�[�W����������
1093     else {
1094     int rsa1_key_bits=0;
1095     rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1096    
1097     if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1098     if (!SSHv1(pvar)) {
1099     do_write = 1;
1100     }
1101     }
1102     else { // �t�@�C�����L�[�� ssh2
1103     if (!SSHv2(pvar)) {
1104     do_write = 1;
1105     }
1106     }
1107     }
1108     }
1109    
1110     // ������������
1111     if (do_write) {
1112     length = pvar->hosts_state.file_data_index - data_index;
1113     amount_written =
1114     _write(fd, pvar->hosts_state.file_data + data_index,
1115 maya 3003 length);
1116 yutakakn 2861
1117     if (amount_written != length) {
1118     goto error1;
1119     }
1120     }
1121     data_index = pvar->hosts_state.file_data_index;
1122     } while (1); // ������������
1123    
1124     error1:
1125     close_result = _close(fd);
1126     if (amount_written != length || close_result == -1) {
1127 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1128 maya 3003 "An error occurred while trying to write the host key.\n"
1129     "The host key could not be written.");
1130 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1131 yutakakn 2861 goto error2;
1132     }
1133    
1134     // �������������t�@�C���������l�[��
1135 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1136 yutakakn 2876 _unlink(buf);
1137     rename(filename, buf);
1138 yutakakn 2861
1139     error2:
1140     _unlink(filename);
1141    
1142     finish_read_host_files(pvar, 0);
1143     }
1144     }
1145    
1146     //
1147 yutakakn 2856 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1148     // ���[�U���m�F�������B
1149     // TODO: finger print���\�����s���B
1150     // (2006.3.25 yutaka)
1151     //
1152 yutakakn 2861 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1153 maya 3003 LPARAM lParam)
1154 yutakakn 2728 {
1155     PTInstVar pvar;
1156 maya 2943 LOGFONT logfont;
1157     HFONT font;
1158 maya 2994 char uimsg[MAX_UIMSG];
1159 yutakakn 2728
1160     switch (msg) {
1161     case WM_INITDIALOG:
1162     pvar = (PTInstVar) lParam;
1163     pvar->hosts_state.hosts_dialog = dlg;
1164     SetWindowLong(dlg, DWL_USER, lParam);
1165    
1166 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1167 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1168     UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1169 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1170 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1171     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1172 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1173 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1174     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1175 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1176 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1177     UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1178 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1179 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1180     UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1181 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1182 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1183     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1184 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1185 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1186     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1187 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1188    
1189 yutakakn 2728 init_hosts_dlg(pvar, dlg);
1190 yutakakn 2856
1191 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1192     GetObject(font, sizeof(LOGFONT), &logfont);
1193 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1194 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1195     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1196     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1197     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1198     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1199     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1200     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1201     }
1202     else {
1203     DlgHostsAddFont = NULL;
1204     }
1205    
1206 yutakakn 2856 // add host check box���`�F�b�N���f�t�H���g������������
1207     SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1208    
1209 yutakakn 2728 return TRUE; /* because we do not set the focus */
1210    
1211     case WM_COMMAND:
1212     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1213    
1214     switch (LOWORD(wParam)) {
1215     case IDC_CONTINUE:
1216     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1217     add_host_key(pvar);
1218     }
1219    
1220 yutakakn 2856 if (SSHv1(pvar)) {
1221     SSH_notify_host_OK(pvar);
1222     } else { // SSH2
1223     // SSH2���������� SSH_notify_host_OK() �������B
1224     }
1225    
1226 yutakakn 2728 pvar->hosts_state.hosts_dialog = NULL;
1227    
1228     EndDialog(dlg, 1);
1229 maya 2943
1230     if (DlgHostsAddFont != NULL) {
1231     DeleteObject(DlgHostsAddFont);
1232     }
1233    
1234 yutakakn 2728 return TRUE;
1235    
1236     case IDCANCEL: /* kill the connection */
1237     pvar->hosts_state.hosts_dialog = NULL;
1238     notify_closed_connection(pvar);
1239     EndDialog(dlg, 0);
1240 maya 2943
1241     if (DlgHostsAddFont != NULL) {
1242     DeleteObject(DlgHostsAddFont);
1243     }
1244    
1245 yutakakn 2728 return TRUE;
1246    
1247     default:
1248     return FALSE;
1249     }
1250    
1251     default:
1252     return FALSE;
1253     }
1254     }
1255    
1256 yutakakn 2861 //
1257     // �u�����������m�F�_�C�A���O������
1258     //
1259     static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1260 maya 3003 LPARAM lParam)
1261 yutakakn 2728 {
1262 yutakakn 2861 PTInstVar pvar;
1263 maya 2943 LOGFONT logfont;
1264     HFONT font;
1265 maya 2994 char uimsg[MAX_UIMSG];
1266 yutakakn 2728
1267 yutakakn 2861 switch (msg) {
1268     case WM_INITDIALOG:
1269     pvar = (PTInstVar) lParam;
1270     pvar->hosts_state.hosts_dialog = dlg;
1271     SetWindowLong(dlg, DWL_USER, lParam);
1272    
1273 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1274 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1275     UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1276 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1277 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1278     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1279 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1280 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1281     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1282 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1283 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1284     UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1285 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1286 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1287     UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1288 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1289 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1290     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1291 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1292 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1293     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1294 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1295    
1296 yutakakn 2861 init_hosts_dlg(pvar, dlg);
1297    
1298 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1299     GetObject(font, sizeof(LOGFONT), &logfont);
1300 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1301 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1302     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1303     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1304     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1305     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1306     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1307     }
1308     else {
1309     DlgHostsReplaceFont = NULL;
1310     }
1311    
1312 yutakakn 2861 // �f�t�H���g���`�F�b�N����������
1313     return TRUE; /* because we do not set the focus */
1314    
1315     case WM_COMMAND:
1316     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1317    
1318     switch (LOWORD(wParam)) {
1319     case IDC_CONTINUE:
1320     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1321     add_host_key(pvar);
1322     delete_different_key(pvar);
1323     }
1324    
1325     if (SSHv1(pvar)) {
1326     SSH_notify_host_OK(pvar);
1327     } else { // SSH2
1328     // SSH2���������� SSH_notify_host_OK() �������B
1329     }
1330    
1331     pvar->hosts_state.hosts_dialog = NULL;
1332    
1333     EndDialog(dlg, 1);
1334 maya 2943
1335     if (DlgHostsReplaceFont != NULL) {
1336     DeleteObject(DlgHostsReplaceFont);
1337     }
1338    
1339 yutakakn 2861 return TRUE;
1340    
1341     case IDCANCEL: /* kill the connection */
1342     pvar->hosts_state.hosts_dialog = NULL;
1343     notify_closed_connection(pvar);
1344     EndDialog(dlg, 0);
1345 maya 2943
1346     if (DlgHostsReplaceFont != NULL) {
1347     DeleteObject(DlgHostsReplaceFont);
1348     }
1349    
1350 yutakakn 2861 return TRUE;
1351    
1352     default:
1353     return FALSE;
1354     }
1355    
1356     default:
1357     return FALSE;
1358 yutakakn 2728 }
1359     }
1360    
1361     void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1362     {
1363     if (pvar->hosts_state.hosts_dialog == NULL) {
1364     HWND cur_active = GetActiveWindow();
1365    
1366     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1367 maya 3003 cur_active != NULL ? cur_active : wnd,
1368     hosts_add_dlg_proc, (LPARAM) pvar);
1369 yutakakn 2728 }
1370     }
1371    
1372     void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1373     {
1374     if (pvar->hosts_state.hosts_dialog == NULL) {
1375     HWND cur_active = GetActiveWindow();
1376    
1377     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1378 maya 3003 cur_active != NULL ? cur_active : wnd,
1379     hosts_replace_dlg_proc, (LPARAM) pvar);
1380 yutakakn 2728 }
1381     }
1382    
1383 yutakakn 2856 //
1384     // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1385     //
1386     // SSH2���������� (2006.3.24 yutaka)
1387     //
1388     BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, Key *key)
1389 yutakakn 2728 {
1390     int found_different_key = 0;
1391    
1392 yutakakn 2856 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1393 yutakakn 2728 if (pvar->hosts_state.prefetched_hostname != NULL
1394 maya 3003 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1395     && match_key(pvar, key)) {
1396 yutakakn 2856
1397     if (SSHv1(pvar)) {
1398     SSH_notify_host_OK(pvar);
1399     } else {
1400     // SSH2���������� SSH_notify_host_OK() �������B
1401     }
1402 yutakakn 2728 return TRUE;
1403     }
1404    
1405 yutakakn 2856 // �������������������������A�������_���t�@�C��������������
1406 yutakakn 2728 if (begin_read_host_files(pvar, 0)) {
1407     do {
1408 yutakakn 2861 if (!read_host_key(pvar, hostname, 0, 0)) {
1409 yutakakn 2728 break;
1410     }
1411    
1412 yutakakn 2856 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1413     if (match_key(pvar, key)) {
1414 yutakakn 2728 finish_read_host_files(pvar, 0);
1415 yutakakn 2859 // ���������G���g�����Q�������A���v�����L�[�������������������B
1416     // SSH2���������������������������B(2006.3.29 yutaka)
1417     if (SSHv1(pvar)) {
1418     SSH_notify_host_OK(pvar);
1419     } else {
1420     // SSH2���������� SSH_notify_host_OK() �������B
1421     }
1422 yutakakn 2728 return TRUE;
1423     } else {
1424 yutakakn 2856 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1425 yutakakn 2728 found_different_key = 1;
1426     }
1427     }
1428 yutakakn 2856 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1429 yutakakn 2728
1430     finish_read_host_files(pvar, 0);
1431     }
1432    
1433 yutakakn 2856
1434     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1435     pvar->hosts_state.hostkey.type = key->type;
1436     if (key->type == KEY_RSA1) { // SSH1
1437     pvar->hosts_state.hostkey.bits = key->bits;
1438     pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1439     pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1440    
1441     } else if (key->type == KEY_RSA) { // SSH2 RSA
1442     pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1443    
1444     } else { // SSH2 DSA
1445     pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1446    
1447     }
1448 yutakakn 2728 free(pvar->hosts_state.prefetched_hostname);
1449     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1450    
1451 yutakapon 3017 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1452     // �������K�v�����������A�����R�[�������X�����B
1453     // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1454     // (2007.10.1 yutaka)
1455 yutakakn 2728 if (found_different_key) {
1456 yutakapon 3017 #if 0
1457 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1458 maya 3003 ID_SSHDIFFERENTHOST, 0);
1459 yutakapon 3017 #else
1460     HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1461     #endif
1462 yutakakn 2728 } else {
1463 yutakapon 3017 #if 0
1464 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1465 maya 3003 ID_SSHUNKNOWNHOST, 0);
1466 yutakapon 3017 #else
1467     HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1468     #endif
1469    
1470 yutakakn 2728 }
1471    
1472     return TRUE;
1473     }
1474    
1475     void HOSTS_notify_disconnecting(PTInstVar pvar)
1476     {
1477     if (pvar->hosts_state.hosts_dialog != NULL) {
1478     PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1479 maya 3003 0);
1480 yutakakn 2728 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1481     EnableWindow(pvar->NotificationWindow, TRUE);
1482     }
1483     }
1484    
1485     void HOSTS_end(PTInstVar pvar)
1486     {
1487     int i;
1488    
1489     free(pvar->hosts_state.prefetched_hostname);
1490 yutakakn 2856 #if 0
1491 yutakakn 2728 free(pvar->hosts_state.key_exp);
1492     free(pvar->hosts_state.key_mod);
1493 yutakakn 2856 #else
1494     init_hostkey(&pvar->hosts_state.hostkey);
1495     #endif
1496 yutakakn 2728
1497     if (pvar->hosts_state.file_names != NULL) {
1498     for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1499     free(pvar->hosts_state.file_names[i]);
1500     }
1501     free(pvar->hosts_state.file_names);
1502     }
1503     }

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