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 3137 - (hide annotations) (download) (as text)
Fri Jul 25 15:48:44 2008 UTC (15 years, 8 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42738 byte(s)
*** empty log message ***

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     free(filename);
1071     return;
1072     }
1073    
1074     // ���������T�[�o���L�[����������
1075     if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1076     key.type = KEY_RSA1;
1077     key.bits = pvar->hosts_state.hostkey.bits;
1078     key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1079     key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1080     } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1081     key.type = KEY_RSA;
1082     key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1083     } else { // SSH2 DSA
1084     key.type = KEY_DSA;
1085     key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1086     }
1087    
1088     // �t�@�C��������������
1089     begin_read_host_files(pvar, 0);
1090     do {
1091     int host_index = 0;
1092     int matched = 0;
1093     int keybits = 0;
1094     char FAR *data;
1095     int do_write = 0;
1096     length = amount_written = 0;
1097    
1098 maya 3126 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1099 yutakakn 2861 break;
1100     }
1101    
1102     if (data_index == pvar->hosts_state.file_data_index) {
1103     // index ���i������ == ��������������
1104     break;
1105     }
1106    
1107     data = pvar->hosts_state.file_data + data_index;
1108     host_index = eat_spaces(data);
1109    
1110     if (data[host_index] == '#') {
1111     do_write = 1;
1112     }
1113     else {
1114     // �z�X�g������
1115     host_index--;
1116     do {
1117     int negated;
1118 maya 3127 int bracketed;
1119     char *end_bracket;
1120     int host_matched = 0;
1121     unsigned short keyfile_port = 22;
1122 yutakakn 2861
1123     host_index++;
1124     negated = data[host_index] == '!';
1125    
1126     if (negated) {
1127     host_index++;
1128 maya 3127 bracketed = data[host_index] == '[';
1129     if (bracketed) {
1130     end_bracket = strstr(data + host_index + 1, "]:");
1131     if (end_bracket != NULL) {
1132     *end_bracket = ' ';
1133     host_index++;
1134     }
1135     }
1136     host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1137     if (bracketed && end_bracket != NULL) {
1138     *end_bracket = ']';
1139     keyfile_port = atoi(end_bracket + 2);
1140     }
1141     if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1142 yutakakn 2861 matched = 0;
1143     // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1144     host_index--;
1145     do {
1146     host_index++;
1147     host_index += eat_to_end_of_pattern(data + host_index);
1148     } while (data[host_index] == ',');
1149     break;
1150     }
1151     }
1152 maya 3127 else {
1153     bracketed = data[host_index] == '[';
1154     if (bracketed) {
1155     end_bracket = strstr(data + host_index + 1, "]:");
1156     if (end_bracket != NULL) {
1157     *end_bracket = ' ';
1158     host_index++;
1159     }
1160     }
1161     host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1162     if (bracketed && end_bracket != NULL) {
1163     *end_bracket = ']';
1164     keyfile_port = atoi(end_bracket + 2);
1165     }
1166     if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1167     matched = 1;
1168     }
1169 yutakakn 2861 }
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 maya 3003 length);
1205 yutakakn 2861
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 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1217 maya 3003 "An error occurred while trying to write the host key.\n"
1218     "The host key could not be written.");
1219 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1220 yutakakn 2861 goto error2;
1221     }
1222    
1223     // �������������t�@�C���������l�[��
1224 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1225 yutakakn 2876 _unlink(buf);
1226     rename(filename, buf);
1227 yutakakn 2861
1228     error2:
1229     _unlink(filename);
1230    
1231     finish_read_host_files(pvar, 0);
1232     }
1233     }
1234    
1235     //
1236 yutakakn 2856 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1237     // ���[�U���m�F�������B
1238     // TODO: finger print���\�����s���B
1239     // (2006.3.25 yutaka)
1240     //
1241 yutakakn 2861 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1242 maya 3003 LPARAM lParam)
1243 yutakakn 2728 {
1244     PTInstVar pvar;
1245 maya 2943 LOGFONT logfont;
1246     HFONT font;
1247 maya 2994 char uimsg[MAX_UIMSG];
1248 yutakakn 2728
1249     switch (msg) {
1250     case WM_INITDIALOG:
1251     pvar = (PTInstVar) lParam;
1252     pvar->hosts_state.hosts_dialog = dlg;
1253     SetWindowLong(dlg, DWL_USER, lParam);
1254    
1255 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1256 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1257     UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1258 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1259 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1260     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1261 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1262 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1263     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1264 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1265 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1266     UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1267 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1268 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1269     UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1270 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1271 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1272     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1273 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1274 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1275     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1276 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1277    
1278 yutakakn 2728 init_hosts_dlg(pvar, dlg);
1279 yutakakn 2856
1280 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1281     GetObject(font, sizeof(LOGFONT), &logfont);
1282 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1283 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1284     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1285     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1286     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1287     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1288     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1289     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1290     }
1291     else {
1292     DlgHostsAddFont = NULL;
1293     }
1294    
1295 yutakakn 2856 // add host check box���`�F�b�N���f�t�H���g������������
1296     SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1297    
1298 yutakakn 2728 return TRUE; /* because we do not set the focus */
1299    
1300     case WM_COMMAND:
1301     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1302    
1303     switch (LOWORD(wParam)) {
1304     case IDC_CONTINUE:
1305     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1306     add_host_key(pvar);
1307     }
1308    
1309 yutakakn 2856 if (SSHv1(pvar)) {
1310     SSH_notify_host_OK(pvar);
1311     } else { // SSH2
1312     // SSH2���������� SSH_notify_host_OK() �������B
1313     }
1314    
1315 yutakakn 2728 pvar->hosts_state.hosts_dialog = NULL;
1316    
1317     EndDialog(dlg, 1);
1318 maya 2943
1319     if (DlgHostsAddFont != NULL) {
1320     DeleteObject(DlgHostsAddFont);
1321     }
1322    
1323 yutakakn 2728 return TRUE;
1324    
1325     case IDCANCEL: /* kill the connection */
1326     pvar->hosts_state.hosts_dialog = NULL;
1327     notify_closed_connection(pvar);
1328     EndDialog(dlg, 0);
1329 maya 2943
1330     if (DlgHostsAddFont != NULL) {
1331     DeleteObject(DlgHostsAddFont);
1332     }
1333    
1334 yutakakn 2728 return TRUE;
1335    
1336     default:
1337     return FALSE;
1338     }
1339    
1340     default:
1341     return FALSE;
1342     }
1343     }
1344    
1345 yutakakn 2861 //
1346     // �u�����������m�F�_�C�A���O������
1347     //
1348     static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1349 maya 3003 LPARAM lParam)
1350 yutakakn 2728 {
1351 yutakakn 2861 PTInstVar pvar;
1352 maya 2943 LOGFONT logfont;
1353     HFONT font;
1354 maya 2994 char uimsg[MAX_UIMSG];
1355 yutakakn 2728
1356 yutakakn 2861 switch (msg) {
1357     case WM_INITDIALOG:
1358     pvar = (PTInstVar) lParam;
1359     pvar->hosts_state.hosts_dialog = dlg;
1360     SetWindowLong(dlg, DWL_USER, lParam);
1361    
1362 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1363 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1364     UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1365 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1366 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1367     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1368 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1369 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1370     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1371 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1372 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1373     UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1374 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1375 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1376     UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1377 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1378 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1379     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1380 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1381 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1382     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1383 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1384    
1385 yutakakn 2861 init_hosts_dlg(pvar, dlg);
1386    
1387 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1388     GetObject(font, sizeof(LOGFONT), &logfont);
1389 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1390 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1391     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1392     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1393     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1394     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1395     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1396     }
1397     else {
1398     DlgHostsReplaceFont = NULL;
1399     }
1400    
1401 yutakakn 2861 // �f�t�H���g���`�F�b�N����������
1402     return TRUE; /* because we do not set the focus */
1403    
1404     case WM_COMMAND:
1405     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1406    
1407     switch (LOWORD(wParam)) {
1408     case IDC_CONTINUE:
1409     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1410     add_host_key(pvar);
1411     delete_different_key(pvar);
1412     }
1413    
1414     if (SSHv1(pvar)) {
1415     SSH_notify_host_OK(pvar);
1416     } else { // SSH2
1417     // SSH2���������� SSH_notify_host_OK() �������B
1418     }
1419    
1420     pvar->hosts_state.hosts_dialog = NULL;
1421    
1422     EndDialog(dlg, 1);
1423 maya 2943
1424     if (DlgHostsReplaceFont != NULL) {
1425     DeleteObject(DlgHostsReplaceFont);
1426     }
1427    
1428 yutakakn 2861 return TRUE;
1429    
1430     case IDCANCEL: /* kill the connection */
1431     pvar->hosts_state.hosts_dialog = NULL;
1432     notify_closed_connection(pvar);
1433     EndDialog(dlg, 0);
1434 maya 2943
1435     if (DlgHostsReplaceFont != NULL) {
1436     DeleteObject(DlgHostsReplaceFont);
1437     }
1438    
1439 yutakakn 2861 return TRUE;
1440    
1441     default:
1442     return FALSE;
1443     }
1444    
1445     default:
1446     return FALSE;
1447 yutakakn 2728 }
1448     }
1449    
1450     void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1451     {
1452     if (pvar->hosts_state.hosts_dialog == NULL) {
1453     HWND cur_active = GetActiveWindow();
1454    
1455     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1456 maya 3003 cur_active != NULL ? cur_active : wnd,
1457     hosts_add_dlg_proc, (LPARAM) pvar);
1458 yutakakn 2728 }
1459     }
1460    
1461     void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1462     {
1463     if (pvar->hosts_state.hosts_dialog == NULL) {
1464     HWND cur_active = GetActiveWindow();
1465    
1466     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1467 maya 3003 cur_active != NULL ? cur_active : wnd,
1468     hosts_replace_dlg_proc, (LPARAM) pvar);
1469 yutakakn 2728 }
1470     }
1471    
1472 yutakakn 2856 //
1473     // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1474     //
1475     // SSH2���������� (2006.3.24 yutaka)
1476     //
1477 maya 3126 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1478 yutakakn 2728 {
1479     int found_different_key = 0;
1480    
1481 yutakakn 2856 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1482 yutakakn 2728 if (pvar->hosts_state.prefetched_hostname != NULL
1483 maya 3003 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1484     && match_key(pvar, key)) {
1485 yutakakn 2856
1486     if (SSHv1(pvar)) {
1487     SSH_notify_host_OK(pvar);
1488     } else {
1489     // SSH2���������� SSH_notify_host_OK() �������B
1490     }
1491 yutakakn 2728 return TRUE;
1492     }
1493    
1494 yutakakn 2856 // �������������������������A�������_���t�@�C��������������
1495 yutakakn 2728 if (begin_read_host_files(pvar, 0)) {
1496     do {
1497 maya 3126 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1498 yutakakn 2728 break;
1499     }
1500    
1501 yutakakn 2856 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1502     if (match_key(pvar, key)) {
1503 yutakakn 2728 finish_read_host_files(pvar, 0);
1504 yutakakn 2859 // ���������G���g�����Q�������A���v�����L�[�������������������B
1505     // SSH2���������������������������B(2006.3.29 yutaka)
1506     if (SSHv1(pvar)) {
1507     SSH_notify_host_OK(pvar);
1508     } else {
1509     // SSH2���������� SSH_notify_host_OK() �������B
1510     }
1511 yutakakn 2728 return TRUE;
1512     } else {
1513 yutakakn 2856 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1514 yutakakn 2728 found_different_key = 1;
1515     }
1516     }
1517 yutakakn 2856 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1518 yutakakn 2728
1519     finish_read_host_files(pvar, 0);
1520     }
1521    
1522 yutakakn 2856
1523     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1524     pvar->hosts_state.hostkey.type = key->type;
1525     if (key->type == KEY_RSA1) { // SSH1
1526     pvar->hosts_state.hostkey.bits = key->bits;
1527     pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1528     pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1529    
1530     } else if (key->type == KEY_RSA) { // SSH2 RSA
1531     pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1532    
1533     } else { // SSH2 DSA
1534     pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1535    
1536     }
1537 yutakakn 2728 free(pvar->hosts_state.prefetched_hostname);
1538     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1539    
1540 yutakapon 3017 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1541     // �������K�v�����������A�����R�[�������X�����B
1542     // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1543     // (2007.10.1 yutaka)
1544 yutakakn 2728 if (found_different_key) {
1545 yutakapon 3017 #if 0
1546 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1547 maya 3003 ID_SSHDIFFERENTHOST, 0);
1548 yutakapon 3017 #else
1549     HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1550     #endif
1551 yutakakn 2728 } else {
1552 yutakapon 3017 #if 0
1553 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1554 maya 3003 ID_SSHUNKNOWNHOST, 0);
1555 yutakapon 3017 #else
1556     HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1557     #endif
1558    
1559 yutakakn 2728 }
1560    
1561     return TRUE;
1562     }
1563    
1564     void HOSTS_notify_disconnecting(PTInstVar pvar)
1565     {
1566     if (pvar->hosts_state.hosts_dialog != NULL) {
1567     PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1568 maya 3003 0);
1569 yutakakn 2728 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1570     EnableWindow(pvar->NotificationWindow, TRUE);
1571     }
1572     }
1573    
1574     void HOSTS_end(PTInstVar pvar)
1575     {
1576     int i;
1577    
1578     free(pvar->hosts_state.prefetched_hostname);
1579 yutakakn 2856 #if 0
1580 yutakakn 2728 free(pvar->hosts_state.key_exp);
1581     free(pvar->hosts_state.key_mod);
1582 yutakakn 2856 #else
1583     init_hostkey(&pvar->hosts_state.hostkey);
1584     #endif
1585 yutakakn 2728
1586     if (pvar->hosts_state.file_names != NULL) {
1587     for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1588     free(pvar->hosts_state.file_names[i]);
1589     }
1590     free(pvar->hosts_state.file_names);
1591     }
1592     }

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