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 3221 - (hide annotations) (download) (as text)
Tue Mar 24 09:37:20 2009 UTC (15 years ago) by maya
File MIME type: text/x-csrc
File size: 42914 byte(s)
CVS から SVN へ移行: trunk に集約
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 yutakapon 3208 char FAR *name = NULL;
971 yutakakn 2728
972 yutakapon 3208 if ( pvar->hosts_state.file_names != NULL)
973     name = pvar->hosts_state.file_names[0];
974    
975 maya 2879 if (name == NULL || name[0] == 0) {
976 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
977 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
978 doda 3134 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
979 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
980 yutakakn 2728 } else {
981     char FAR *keydata = format_host_key(pvar);
982     int length = strlen(keydata);
983 maya 2879 int fd;
984 yutakakn 2728 int amount_written;
985     int close_result;
986 maya 2879 char buf[FILENAME_MAX];
987 yutakakn 2728
988 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
989     fd = _open(buf,
990 maya 3003 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
991     _S_IREAD | _S_IWRITE);
992 yutakakn 2728 if (fd == -1) {
993     if (errno == EACCES) {
994 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
995 maya 3003 "An error occurred while trying to write the host key.\n"
996     "You do not have permission to write to the known-hosts file.");
997 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
998 yutakakn 2728 } else {
999 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1000 maya 3003 "An error occurred while trying to write the host key.\n"
1001     "The host key could not be written.");
1002 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1003 yutakakn 2728 }
1004     return;
1005     }
1006    
1007     amount_written = _write(fd, keydata, length);
1008     free(keydata);
1009     close_result = _close(fd);
1010    
1011     if (amount_written != length || close_result == -1) {
1012 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1013 maya 3003 "An error occurred while trying to write the host key.\n"
1014     "The host key could not be written.");
1015 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1016 yutakakn 2728 }
1017     }
1018     }
1019    
1020 yutakakn 2861 static char FAR *copy_mp_int(char FAR * num)
1021     {
1022     int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1023     char FAR *result = (char FAR *) malloc(len);
1024    
1025     if (result != NULL) {
1026     memcpy(result, num, len);
1027     }
1028    
1029     return result;
1030     }
1031    
1032 yutakakn 2856 //
1033 yutakakn 2861 // �����z�X�g�����e���������L�[����������
1034     // add_host_key ����������������
1035     //
1036     static void delete_different_key(PTInstVar pvar)
1037     {
1038     char FAR *name = pvar->hosts_state.file_names[0];
1039    
1040 maya 2879 if (name == NULL || name[0] == 0) {
1041 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1042 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1043 doda 3134 "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1044 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1045 yutakakn 2861 }
1046     else {
1047     Key key; // ���������z�X�g���L�[
1048 yutakakn 2876 int length;
1049 maya 3144 char filename[MAX_PATH];
1050     char tmp[L_tmpnam];
1051 yutakakn 2861 int fd;
1052     int amount_written = 0;
1053     int close_result;
1054     int data_index = 0;
1055 maya 2879 char buf[FILENAME_MAX];
1056 yutakakn 2861
1057     // �������������t�@�C�����J��
1058 maya 3144 _getcwd(filename, sizeof(filename));
1059     tmpnam_s(tmp,sizeof(tmp));
1060     strcat_s(filename, sizeof(filename), tmp);
1061 maya 3003 fd = _open(filename,
1062     _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1063     _S_IREAD | _S_IWRITE);
1064 yutakakn 2861
1065     if (fd == -1) {
1066     if (errno == EACCES) {
1067 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1068 maya 3003 "An error occurred while trying to write the host key.\n"
1069     "You do not have permission to write to the known-hosts file.");
1070 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1071 yutakakn 2861 } else {
1072 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1073 maya 3003 "An error occurred while trying to write the host key.\n"
1074     "The host key could not be written.");
1075 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1076 yutakakn 2861 }
1077     return;
1078     }
1079    
1080     // ���������T�[�o���L�[����������
1081     if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1082     key.type = KEY_RSA1;
1083     key.bits = pvar->hosts_state.hostkey.bits;
1084     key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1085     key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1086     } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1087     key.type = KEY_RSA;
1088     key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1089     } else { // SSH2 DSA
1090     key.type = KEY_DSA;
1091     key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1092     }
1093    
1094     // �t�@�C��������������
1095     begin_read_host_files(pvar, 0);
1096     do {
1097     int host_index = 0;
1098     int matched = 0;
1099     int keybits = 0;
1100     char FAR *data;
1101     int do_write = 0;
1102     length = amount_written = 0;
1103    
1104 maya 3126 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1105 yutakakn 2861 break;
1106     }
1107    
1108     if (data_index == pvar->hosts_state.file_data_index) {
1109     // index ���i������ == ��������������
1110     break;
1111     }
1112    
1113     data = pvar->hosts_state.file_data + data_index;
1114     host_index = eat_spaces(data);
1115    
1116     if (data[host_index] == '#') {
1117     do_write = 1;
1118     }
1119     else {
1120     // �z�X�g������
1121     host_index--;
1122     do {
1123     int negated;
1124 maya 3127 int bracketed;
1125     char *end_bracket;
1126     int host_matched = 0;
1127     unsigned short keyfile_port = 22;
1128 yutakakn 2861
1129     host_index++;
1130     negated = data[host_index] == '!';
1131    
1132     if (negated) {
1133     host_index++;
1134 maya 3127 bracketed = data[host_index] == '[';
1135     if (bracketed) {
1136     end_bracket = strstr(data + host_index + 1, "]:");
1137     if (end_bracket != NULL) {
1138     *end_bracket = ' ';
1139     host_index++;
1140     }
1141     }
1142     host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1143     if (bracketed && end_bracket != NULL) {
1144     *end_bracket = ']';
1145     keyfile_port = atoi(end_bracket + 2);
1146     }
1147     if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1148 yutakakn 2861 matched = 0;
1149     // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1150     host_index--;
1151     do {
1152     host_index++;
1153     host_index += eat_to_end_of_pattern(data + host_index);
1154     } while (data[host_index] == ',');
1155     break;
1156     }
1157     }
1158 maya 3127 else {
1159     bracketed = data[host_index] == '[';
1160     if (bracketed) {
1161     end_bracket = strstr(data + host_index + 1, "]:");
1162     if (end_bracket != NULL) {
1163     *end_bracket = ' ';
1164     host_index++;
1165     }
1166     }
1167     host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1168     if (bracketed && end_bracket != NULL) {
1169     *end_bracket = ']';
1170     keyfile_port = atoi(end_bracket + 2);
1171     }
1172     if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1173     matched = 1;
1174     }
1175 yutakakn 2861 }
1176     host_index += eat_to_end_of_pattern(data + host_index);
1177     } while (data[host_index] == ',');
1178    
1179     // �z�X�g�������������v�����L�[����������
1180     if (match_key(pvar, &key)) {
1181     do_write = 1;
1182     }
1183     // �z�X�g������������
1184     else if (!matched) {
1185     do_write = 1;
1186     }
1187     // �z�X�g�������� and �������o�[�W����������
1188     else {
1189     int rsa1_key_bits=0;
1190     rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1191    
1192     if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1193     if (!SSHv1(pvar)) {
1194     do_write = 1;
1195     }
1196     }
1197     else { // �t�@�C�����L�[�� ssh2
1198     if (!SSHv2(pvar)) {
1199     do_write = 1;
1200     }
1201     }
1202     }
1203     }
1204    
1205     // ������������
1206     if (do_write) {
1207     length = pvar->hosts_state.file_data_index - data_index;
1208     amount_written =
1209     _write(fd, pvar->hosts_state.file_data + data_index,
1210 maya 3003 length);
1211 yutakakn 2861
1212     if (amount_written != length) {
1213     goto error1;
1214     }
1215     }
1216     data_index = pvar->hosts_state.file_data_index;
1217     } while (1); // ������������
1218    
1219     error1:
1220     close_result = _close(fd);
1221     if (amount_written != length || close_result == -1) {
1222 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1223 maya 3003 "An error occurred while trying to write the host key.\n"
1224     "The host key could not be written.");
1225 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1226 yutakakn 2861 goto error2;
1227     }
1228    
1229     // �������������t�@�C���������l�[��
1230 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1231 yutakakn 2876 _unlink(buf);
1232     rename(filename, buf);
1233 yutakakn 2861
1234     error2:
1235     _unlink(filename);
1236    
1237     finish_read_host_files(pvar, 0);
1238     }
1239     }
1240    
1241     //
1242 yutakakn 2856 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1243     // ���[�U���m�F�������B
1244     // TODO: finger print���\�����s���B
1245     // (2006.3.25 yutaka)
1246     //
1247 yutakakn 2861 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1248 maya 3003 LPARAM lParam)
1249 yutakakn 2728 {
1250     PTInstVar pvar;
1251 maya 2943 LOGFONT logfont;
1252     HFONT font;
1253 maya 2994 char uimsg[MAX_UIMSG];
1254 yutakakn 2728
1255     switch (msg) {
1256     case WM_INITDIALOG:
1257     pvar = (PTInstVar) lParam;
1258     pvar->hosts_state.hosts_dialog = dlg;
1259     SetWindowLong(dlg, DWL_USER, lParam);
1260    
1261 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1262 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1263     UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1264 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1265 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1266     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1267 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1268 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1269     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1270 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1271 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1272     UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1273 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1274 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1275     UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1276 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1277 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1278     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1279 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1280 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1281     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1282 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1283    
1284 yutakakn 2728 init_hosts_dlg(pvar, dlg);
1285 yutakakn 2856
1286 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1287     GetObject(font, sizeof(LOGFONT), &logfont);
1288 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1289 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1290     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1291     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1292     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1293     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1294     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1295     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1296     }
1297     else {
1298     DlgHostsAddFont = NULL;
1299     }
1300    
1301 yutakakn 2856 // add host check box���`�F�b�N���f�t�H���g������������
1302     SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1303    
1304 yutakakn 2728 return TRUE; /* because we do not set the focus */
1305    
1306     case WM_COMMAND:
1307     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1308    
1309     switch (LOWORD(wParam)) {
1310     case IDC_CONTINUE:
1311     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1312     add_host_key(pvar);
1313     }
1314    
1315 yutakakn 2856 if (SSHv1(pvar)) {
1316     SSH_notify_host_OK(pvar);
1317     } else { // SSH2
1318     // SSH2���������� SSH_notify_host_OK() �������B
1319     }
1320    
1321 yutakakn 2728 pvar->hosts_state.hosts_dialog = NULL;
1322    
1323     EndDialog(dlg, 1);
1324 maya 2943
1325     if (DlgHostsAddFont != NULL) {
1326     DeleteObject(DlgHostsAddFont);
1327     }
1328    
1329 yutakakn 2728 return TRUE;
1330    
1331     case IDCANCEL: /* kill the connection */
1332     pvar->hosts_state.hosts_dialog = NULL;
1333     notify_closed_connection(pvar);
1334     EndDialog(dlg, 0);
1335 maya 2943
1336     if (DlgHostsAddFont != NULL) {
1337     DeleteObject(DlgHostsAddFont);
1338     }
1339    
1340 yutakakn 2728 return TRUE;
1341    
1342     default:
1343     return FALSE;
1344     }
1345    
1346     default:
1347     return FALSE;
1348     }
1349     }
1350    
1351 yutakakn 2861 //
1352     // �u�����������m�F�_�C�A���O������
1353     //
1354     static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1355 maya 3003 LPARAM lParam)
1356 yutakakn 2728 {
1357 yutakakn 2861 PTInstVar pvar;
1358 maya 2943 LOGFONT logfont;
1359     HFONT font;
1360 maya 2994 char uimsg[MAX_UIMSG];
1361 yutakakn 2728
1362 yutakakn 2861 switch (msg) {
1363     case WM_INITDIALOG:
1364     pvar = (PTInstVar) lParam;
1365     pvar->hosts_state.hosts_dialog = dlg;
1366     SetWindowLong(dlg, DWL_USER, lParam);
1367    
1368 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1369 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1370     UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1371 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1372 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1373     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1374 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1375 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1376     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1377 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1378 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1379     UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1380 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1381 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1382     UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1383 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1384 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1385     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1386 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1387 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1388     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1389 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1390    
1391 yutakakn 2861 init_hosts_dlg(pvar, dlg);
1392    
1393 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1394     GetObject(font, sizeof(LOGFONT), &logfont);
1395 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1396 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1397     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1398     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1399     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1400     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1401     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1402     }
1403     else {
1404     DlgHostsReplaceFont = NULL;
1405     }
1406    
1407 yutakakn 2861 // �f�t�H���g���`�F�b�N����������
1408     return TRUE; /* because we do not set the focus */
1409    
1410     case WM_COMMAND:
1411     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1412    
1413     switch (LOWORD(wParam)) {
1414     case IDC_CONTINUE:
1415     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1416     add_host_key(pvar);
1417     delete_different_key(pvar);
1418     }
1419    
1420     if (SSHv1(pvar)) {
1421     SSH_notify_host_OK(pvar);
1422     } else { // SSH2
1423     // SSH2���������� SSH_notify_host_OK() �������B
1424     }
1425    
1426     pvar->hosts_state.hosts_dialog = NULL;
1427    
1428     EndDialog(dlg, 1);
1429 maya 2943
1430     if (DlgHostsReplaceFont != NULL) {
1431     DeleteObject(DlgHostsReplaceFont);
1432     }
1433    
1434 yutakakn 2861 return TRUE;
1435    
1436     case IDCANCEL: /* kill the connection */
1437     pvar->hosts_state.hosts_dialog = NULL;
1438     notify_closed_connection(pvar);
1439     EndDialog(dlg, 0);
1440 maya 2943
1441     if (DlgHostsReplaceFont != NULL) {
1442     DeleteObject(DlgHostsReplaceFont);
1443     }
1444    
1445 yutakakn 2861 return TRUE;
1446    
1447     default:
1448     return FALSE;
1449     }
1450    
1451     default:
1452     return FALSE;
1453 yutakakn 2728 }
1454     }
1455    
1456     void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1457     {
1458     if (pvar->hosts_state.hosts_dialog == NULL) {
1459     HWND cur_active = GetActiveWindow();
1460    
1461     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1462 maya 3003 cur_active != NULL ? cur_active : wnd,
1463     hosts_add_dlg_proc, (LPARAM) pvar);
1464 yutakakn 2728 }
1465     }
1466    
1467     void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1468     {
1469     if (pvar->hosts_state.hosts_dialog == NULL) {
1470     HWND cur_active = GetActiveWindow();
1471    
1472     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1473 maya 3003 cur_active != NULL ? cur_active : wnd,
1474     hosts_replace_dlg_proc, (LPARAM) pvar);
1475 yutakakn 2728 }
1476     }
1477    
1478 yutakakn 2856 //
1479     // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1480     //
1481     // SSH2���������� (2006.3.24 yutaka)
1482     //
1483 maya 3126 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1484 yutakakn 2728 {
1485     int found_different_key = 0;
1486    
1487 yutakakn 2856 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1488 yutakakn 2728 if (pvar->hosts_state.prefetched_hostname != NULL
1489 maya 3003 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1490     && match_key(pvar, key)) {
1491 yutakakn 2856
1492     if (SSHv1(pvar)) {
1493     SSH_notify_host_OK(pvar);
1494     } else {
1495     // SSH2���������� SSH_notify_host_OK() �������B
1496     }
1497 yutakakn 2728 return TRUE;
1498     }
1499    
1500 yutakakn 2856 // �������������������������A�������_���t�@�C��������������
1501 yutakakn 2728 if (begin_read_host_files(pvar, 0)) {
1502     do {
1503 maya 3126 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1504 yutakakn 2728 break;
1505     }
1506    
1507 yutakakn 2856 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1508     if (match_key(pvar, key)) {
1509 yutakakn 2728 finish_read_host_files(pvar, 0);
1510 yutakakn 2859 // ���������G���g�����Q�������A���v�����L�[�������������������B
1511     // SSH2���������������������������B(2006.3.29 yutaka)
1512     if (SSHv1(pvar)) {
1513     SSH_notify_host_OK(pvar);
1514     } else {
1515     // SSH2���������� SSH_notify_host_OK() �������B
1516     }
1517 yutakakn 2728 return TRUE;
1518     } else {
1519 yutakakn 2856 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1520 yutakakn 2728 found_different_key = 1;
1521     }
1522     }
1523 yutakakn 2856 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1524 yutakakn 2728
1525     finish_read_host_files(pvar, 0);
1526     }
1527    
1528 yutakakn 2856
1529     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1530     pvar->hosts_state.hostkey.type = key->type;
1531     if (key->type == KEY_RSA1) { // SSH1
1532     pvar->hosts_state.hostkey.bits = key->bits;
1533     pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1534     pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1535    
1536     } else if (key->type == KEY_RSA) { // SSH2 RSA
1537     pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1538    
1539     } else { // SSH2 DSA
1540     pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1541    
1542     }
1543 yutakakn 2728 free(pvar->hosts_state.prefetched_hostname);
1544     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1545    
1546 yutakapon 3017 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1547     // �������K�v�����������A�����R�[�������X�����B
1548     // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1549     // (2007.10.1 yutaka)
1550 yutakakn 2728 if (found_different_key) {
1551 yutakapon 3017 #if 0
1552 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1553 maya 3003 ID_SSHDIFFERENTHOST, 0);
1554 yutakapon 3017 #else
1555     HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1556     #endif
1557 yutakakn 2728 } else {
1558 yutakapon 3017 #if 0
1559 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1560 maya 3003 ID_SSHUNKNOWNHOST, 0);
1561 yutakapon 3017 #else
1562     HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1563     #endif
1564    
1565 yutakakn 2728 }
1566    
1567     return TRUE;
1568     }
1569    
1570     void HOSTS_notify_disconnecting(PTInstVar pvar)
1571     {
1572     if (pvar->hosts_state.hosts_dialog != NULL) {
1573     PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1574 maya 3003 0);
1575 yutakakn 2728 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1576     EnableWindow(pvar->NotificationWindow, TRUE);
1577     }
1578     }
1579    
1580     void HOSTS_end(PTInstVar pvar)
1581     {
1582     int i;
1583    
1584     free(pvar->hosts_state.prefetched_hostname);
1585 yutakakn 2856 #if 0
1586 yutakakn 2728 free(pvar->hosts_state.key_exp);
1587     free(pvar->hosts_state.key_mod);
1588 yutakakn 2856 #else
1589     init_hostkey(&pvar->hosts_state.hostkey);
1590     #endif
1591 yutakakn 2728
1592     if (pvar->hosts_state.file_names != NULL) {
1593     for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1594     free(pvar->hosts_state.file_names[i]);
1595     }
1596     free(pvar->hosts_state.file_names);
1597     }
1598     }

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