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 3144 - (hide annotations) (download) (as text)
Wed Sep 3 17:05:44 2008 UTC (15 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42854 byte(s)
ssh_knwon_hosts の鍵の置換で、一時書き込みファイルをフルパスで開くようにした。
http://sourceforge.jp/tracker/index.php?func=detail&aid=13353&group_id=1412&atid=5333

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

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