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 2942 - (hide annotations) (download) (as text)
Tue Dec 5 09:20:36 2006 UTC (17 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 40940 byte(s)
表示メッセージの読み込み対応

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

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