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 3143 - (hide annotations) (download) (as text)
Mon Sep 1 05:13:11 2008 UTC (15 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42719 byte(s)
http://sourceforge.jp/tracker/index.php?func=detail&aid=13353&group_id=1412&atid=5333
tmpnam で受け取ったファイル名は free してはいけないらしい。
notify_nonfatal_error が出ない問題はこの修正で回避される。

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

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