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 3127 - (hide annotations) (download) (as text)
Mon May 19 12:03:55 2008 UTC (15 years, 10 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 42403 byte(s)
known_hosts のポート番号をサポートした。

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

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