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 3120 - (hide annotations) (download) (as text)
Sun Mar 2 13:54:43 2008 UTC (16 years, 1 month ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 39945 byte(s)
メモリリークの修正。

1 yutakakn 2728 /*
2     Copyright (c) 1998-2001, Robert O'Callahan
3     All rights reserved.
4    
5     Redistribution and use in source and binary forms, with or without modification,
6     are permitted provided that the following conditions are met:
7    
8     Redistributions of source code must retain the above copyright notice, this list of
9     conditions and the following disclaimer.
10    
11     Redistributions in binary form must reproduce the above copyright notice, this list
12     of conditions and the following disclaimer in the documentation and/or other materials
13     provided with the distribution.
14    
15     The name of Robert O'Callahan may not be used to endorse or promote products derived from
16     this software without specific prior written permission.
17    
18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21     THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27     */
28    
29     /*
30     This code is copyright (C) 1998-1999 Robert O'Callahan.
31     See LICENSE.TXT for the license.
32     */
33    
34     #include "ttxssh.h"
35     #include "util.h"
36     #include "resource.h"
37     #include "matcher.h"
38 yutakakn 2856 #include "ssh.h"
39     #include "hosts.h"
40 yutakakn 2728
41     #include <openssl/bn.h>
42 yutakakn 2856 #include <openssl/evp.h>
43     #include <openssl/rsa.h>
44     #include <openssl/dsa.h>
45 yutakakn 2728
46     #include <fcntl.h>
47     #include <io.h>
48     #include <errno.h>
49     #include <sys/stat.h>
50    
51 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 3003 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    
519     index++;
520     negated = data[index] == '!';
521    
522     if (negated) {
523     index++;
524     if (match_pattern(data + index, hostname)) {
525     return index + eat_to_end_of_line(data + index);
526     }
527     } else if (match_pattern(data + index, hostname)) {
528     matched = 1;
529     }
530    
531     index += eat_to_end_of_pattern(data + index);
532     } while (data[index] == ',');
533    
534     if (!matched) {
535     return index + eat_to_end_of_line(data + index);
536     } else {
537 yutakakn 2856 // ���������������t�H�[�}�b�g��������
538     // �����A���������v�����G���g�����������������������B
539     /*
540     [SSH1]
541     192.168.1.2 1024 35 13032....
542 yutakakn 2728
543 yutakakn 2856 [SSH2]
544     192.168.1.2 ssh-rsa AAAAB3NzaC1....
545     192.168.1.2 ssh-dss AAAAB3NzaC1....
546     192.168.1.2 rsa AAAAB3NzaC1....
547     192.168.1.2 dsa AAAAB3NzaC1....
548     192.168.1.2 rsa1 AAAAB3NzaC1....
549     */
550     int rsa1_key_bits;
551 yutakakn 2728
552     index += eat_spaces(data + index);
553    
554 yutakakn 2856 rsa1_key_bits = atoi(data + index);
555     if (rsa1_key_bits > 0) { // RSA1������
556     if (!SSHv1(pvar)) { // SSH2��������������������
557     return index + eat_to_end_of_line(data + index);
558     }
559 yutakakn 2728
560 yutakakn 2856 pvar->hosts_state.hostkey.type = KEY_RSA1;
561    
562     pvar->hosts_state.hostkey.bits = rsa1_key_bits;
563     index += eat_digits(data + index);
564     index += eat_spaces(data + index);
565    
566     pvar->hosts_state.hostkey.exp = parse_bignum(data + index);
567     index += eat_digits(data + index);
568     index += eat_spaces(data + index);
569    
570     pvar->hosts_state.hostkey.mod = parse_bignum(data + index);
571    
572     /*
573     if (pvar->hosts_state.key_bits < 0
574     || pvar->hosts_state.key_exp == NULL
575     || pvar->hosts_state.key_mod == NULL) {
576     pvar->hosts_state.key_bits = 0;
577     free(pvar->hosts_state.key_exp);
578     free(pvar->hosts_state.key_mod);
579     }*/
580    
581     } else {
582     char *cp, *p;
583     Key *key;
584    
585     if (!SSHv2(pvar)) { // SSH1��������������������
586     return index + eat_to_end_of_line(data + index);
587     }
588    
589     cp = data + index;
590     p = strchr(cp, ' ');
591     if (p == NULL) {
592     return index + eat_to_end_of_line(data + index);
593     }
594     index += (p - cp); // setup index
595     *p = '\0';
596     pvar->hosts_state.hostkey.type = get_keytype_from_name(cp);
597     *p = ' ';
598    
599     index += eat_spaces(data + index); // update index
600    
601     // uudecode
602     key = parse_uudecode(data + index);
603     if (key == NULL) {
604     return index + eat_to_end_of_line(data + index);
605     }
606    
607     // setup
608     pvar->hosts_state.hostkey.type = key->type;
609     pvar->hosts_state.hostkey.dsa = key->dsa;
610     pvar->hosts_state.hostkey.rsa = key->rsa;
611    
612     index += eat_base64(data + index);
613     index += eat_spaces(data + index);
614 yutakapon 3120
615     // Key�\�������g���������� (2008.3.2 yutaka)
616     free(key);
617 yutakakn 2728 }
618    
619     return index + eat_to_end_of_line(data + index);
620     }
621     }
622    
623 yutakakn 2856 //
624     // known_hosts�t�@�C�������z�X�g�������v�����s������
625     //
626 yutakakn 2728 static int read_host_key(PTInstVar pvar, char FAR * hostname,
627 maya 3003 int suppress_errors, int return_always)
628 yutakakn 2728 {
629     int i;
630 yutakakn 2861 int while_flg;
631 yutakakn 2728
632     for (i = 0; hostname[i] != 0; i++) {
633     int ch = hostname[i];
634    
635     if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
636     if (!suppress_errors) {
637 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
638 maya 3003 "The host name contains an invalid character.\n"
639     "This session will be terminated.");
640 maya 2942 notify_fatal_error(pvar, pvar->ts->UIMsg);
641 yutakakn 2728 }
642     return 0;
643     }
644     }
645    
646     if (i == 0) {
647     if (!suppress_errors) {
648 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
649 maya 3003 "The host name should not be empty.\n"
650     "This session will be terminated.");
651 maya 2942 notify_fatal_error(pvar, pvar->ts->UIMsg);
652 yutakakn 2728 }
653     return 0;
654     }
655    
656 yutakakn 2856 #if 0
657 yutakakn 2728 pvar->hosts_state.key_bits = 0;
658     free(pvar->hosts_state.key_exp);
659     pvar->hosts_state.key_exp = NULL;
660     free(pvar->hosts_state.key_mod);
661     pvar->hosts_state.key_mod = NULL;
662 yutakakn 2856 #else
663     // hostkey type is KEY_UNSPEC.
664     init_hostkey(&pvar->hosts_state.hostkey);
665     #endif
666 yutakakn 2728
667     do {
668     if (pvar->hosts_state.file_data == NULL
669 maya 3003 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
670 yutakakn 2728 char FAR *filename;
671     int keep_going = 1;
672    
673     if (pvar->hosts_state.file_data != NULL) {
674     end_read_file(pvar, suppress_errors);
675     }
676    
677     do {
678     filename =
679 maya 3003 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
680 yutakakn 2728
681     if (filename == NULL) {
682     return 1;
683     } else {
684     pvar->hosts_state.file_num++;
685    
686     if (filename[0] != 0) {
687 maya 3003 if (begin_read_file(pvar, filename, suppress_errors)) {
688 yutakakn 2728 pvar->hosts_state.file_data_index = 0;
689     keep_going = 0;
690     }
691     }
692     }
693     } while (keep_going);
694     }
695    
696     pvar->hosts_state.file_data_index +=
697     check_host_key(pvar, hostname,
698 maya 3003 pvar->hosts_state.file_data +
699     pvar->hosts_state.file_data_index);
700 yutakakn 2728
701 yutakakn 2861 if (!return_always) {
702     // �L�����L�[��������������
703     while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
704     }
705     else {
706     while_flg = 0;
707     }
708     } while (while_flg);
709    
710 yutakakn 2728 return 1;
711     }
712    
713     static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
714     {
715     if (pvar->hosts_state.file_data != NULL) {
716     end_read_file(pvar, suppress_errors);
717     }
718     }
719    
720 yutakakn 2856 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
721 yutakakn 2728 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname)
722     {
723     if (!begin_read_host_files(pvar, 1)) {
724     return;
725     }
726    
727 yutakakn 2861 if (!read_host_key(pvar, hostname, 1, 0)) {
728 yutakakn 2728 return;
729     }
730    
731     free(pvar->hosts_state.prefetched_hostname);
732     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
733    
734     finish_read_host_files(pvar, 1);
735     }
736    
737     static BOOL equal_mp_ints(unsigned char FAR * num1,
738 maya 3003 unsigned char FAR * num2)
739 yutakakn 2728 {
740     if (num1 == NULL || num2 == NULL) {
741     return FALSE;
742     } else {
743     uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
744    
745     if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
746     return FALSE; /* different byte lengths */
747     } else {
748     return memcmp(num1 + 2, num2 + 2, bytes) == 0;
749     }
750     }
751     }
752    
753 yutakakn 2856 // ���J����������������������
754     static BOOL match_key(PTInstVar pvar, Key *key)
755 yutakakn 2728 {
756 yutakakn 2856 int bits;
757     unsigned char FAR * exp;
758     unsigned char FAR * mod;
759    
760     if (key->type == KEY_RSA1) { // SSH1 host public key
761     bits = key->bits;
762     exp = key->exp;
763     mod = key->mod;
764    
765     /* just check for equal exponent and modulus */
766     return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
767 maya 3003 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
768 yutakakn 2856 /*
769     return equal_mp_ints(exp, pvar->hosts_state.key_exp)
770     && equal_mp_ints(mod, pvar->hosts_state.key_mod);
771     */
772    
773     } else if (key->type == KEY_RSA) { // SSH2 RSA host public key
774    
775     return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
776 maya 3003 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
777     BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
778 yutakakn 2856
779     } else { // // SSH2 DSA host public key
780    
781     return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
782 maya 3003 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
783     BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
784     BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
785     BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
786 yutakakn 2856
787     }
788    
789 yutakakn 2728 }
790    
791     static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
792     {
793     char buf[1024];
794     char buf2[2048];
795     int i, j;
796     int ch;
797 yutakakn 2857 char *fp;
798 yutakakn 2728
799 yutakakn 2857 // static text�� # �������z�X�g�����u������
800 yutakakn 2728 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
801     for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
802     buf2[i] = ch;
803     }
804 maya 2992 strncpy_s(buf2 + i, sizeof(buf2) - i,
805 maya 3003 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
806 yutakakn 2728 j = i + strlen(buf2 + i);
807     for (; buf[i] == '#'; i++) {
808     }
809 maya 2992 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
810 yutakakn 2728
811     SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
812 yutakakn 2857
813     // fingerprint����������
814     fp = key_fingerprint(&pvar->hosts_state.hostkey);
815     SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
816 yutakakn 2728 }
817    
818     static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
819     {
820     int i = 0, j, k;
821     BIGNUM *num = BN_new();
822     int ch;
823    
824     BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
825    
826     do {
827     buf[i] = (char) ((BN_div_word(num, 10)) + '0');
828     i++;
829     } while (!BN_is_zero(num));
830    
831     /* we need to reverse the digits */
832     for (j = 0, k = i - 1; j < k; j++, k--) {
833     ch = buf[j];
834     buf[j] = buf[k];
835     buf[k] = ch;
836     }
837    
838     buf[i] = 0;
839     return i;
840     }
841    
842 yutakakn 2856 //
843     // known_hosts �t�@�C�������������G���g�������������B
844     //
845 yutakakn 2728 static char FAR *format_host_key(PTInstVar pvar)
846     {
847     int host_len = strlen(pvar->hosts_state.prefetched_hostname);
848 yutakakn 2856 char *result = NULL;
849     int index;
850     enum hostkey_type type = pvar->hosts_state.hostkey.type;
851    
852     if (type == KEY_RSA1) {
853 maya 2992 int result_len = host_len + 50 +
854 maya 3003 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
855     get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
856 maya 2992 result = (char FAR *) malloc(result_len);
857 yutakakn 2728
858 maya 2992 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
859 yutakakn 2856 index = host_len;
860 yutakakn 2728
861 maya 2992 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
862 maya 3003 " %d ", pvar->hosts_state.hostkey.bits);
863 yutakakn 2856 index += strlen(result + index);
864     index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
865     result[index] = ' ';
866     index++;
867     index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
868 maya 2992 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
869 yutakakn 2728
870 yutakakn 2856 } else if (type == KEY_RSA || type == KEY_DSA) {
871     Key *key = &pvar->hosts_state.hostkey;
872     char *blob = NULL;
873     int blen, uulen, msize;
874     char *uu = NULL;
875     int n;
876    
877     key_to_blob(key, &blob, &blen);
878     uulen = 2 * blen;
879     uu = malloc(uulen);
880     if (uu == NULL) {
881     goto error;
882     }
883     n = uuencode(blob, blen, uu, uulen);
884     if (n > 0) {
885     msize = host_len + 50 + uulen;
886     result = malloc(msize);
887     if (result == NULL) {
888     goto error;
889     }
890    
891     // setup
892 maya 2992 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
893 maya 3003 pvar->hosts_state.prefetched_hostname,
894     get_sshname_from_key(key),
895     uu);
896 yutakakn 2856 }
897     error:
898     if (blob != NULL)
899     free(blob);
900     if (uu != NULL)
901     free(uu);
902    
903     } else {
904     return NULL;
905    
906     }
907    
908 yutakakn 2728 return result;
909     }
910    
911     static void add_host_key(PTInstVar pvar)
912     {
913     char FAR *name = pvar->hosts_state.file_names[0];
914    
915 maya 2879 if (name == NULL || name[0] == 0) {
916 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
917 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
918     "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
919 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
920 yutakakn 2728 } else {
921     char FAR *keydata = format_host_key(pvar);
922     int length = strlen(keydata);
923 maya 2879 int fd;
924 yutakakn 2728 int amount_written;
925     int close_result;
926 maya 2879 char buf[FILENAME_MAX];
927 yutakakn 2728
928 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
929     fd = _open(buf,
930 maya 3003 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
931     _S_IREAD | _S_IWRITE);
932 yutakakn 2728 if (fd == -1) {
933     if (errno == EACCES) {
934 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
935 maya 3003 "An error occurred while trying to write the host key.\n"
936     "You do not have permission to write to the known-hosts file.");
937 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
938 yutakakn 2728 } else {
939 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
940 maya 3003 "An error occurred while trying to write the host key.\n"
941     "The host key could not be written.");
942 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
943 yutakakn 2728 }
944     return;
945     }
946    
947     amount_written = _write(fd, keydata, length);
948     free(keydata);
949     close_result = _close(fd);
950    
951     if (amount_written != length || close_result == -1) {
952 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
953 maya 3003 "An error occurred while trying to write the host key.\n"
954     "The host key could not be written.");
955 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
956 yutakakn 2728 }
957     }
958     }
959    
960 yutakakn 2861 static char FAR *copy_mp_int(char FAR * num)
961     {
962     int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
963     char FAR *result = (char FAR *) malloc(len);
964    
965     if (result != NULL) {
966     memcpy(result, num, len);
967     }
968    
969     return result;
970     }
971    
972 yutakakn 2856 //
973 yutakakn 2861 // �����z�X�g�����e���������L�[����������
974     // add_host_key ����������������
975     //
976     static void delete_different_key(PTInstVar pvar)
977     {
978     char FAR *name = pvar->hosts_state.file_names[0];
979    
980 maya 2879 if (name == NULL || name[0] == 0) {
981 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
982 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
983     "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
984 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
985 yutakakn 2861 }
986     else {
987     Key key; // ���������z�X�g���L�[
988 yutakakn 2876 int length;
989 yutakakn 2861 char filename[L_tmpnam];
990     int fd;
991     int amount_written = 0;
992     int close_result;
993     int data_index = 0;
994 maya 2879 char buf[FILENAME_MAX];
995 yutakakn 2861
996     // �������������t�@�C�����J��
997     tmpnam(filename);
998 maya 3003 fd = _open(filename,
999     _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1000     _S_IREAD | _S_IWRITE);
1001 yutakakn 2861
1002     if (fd == -1) {
1003     if (errno == EACCES) {
1004 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1005 maya 3003 "An error occurred while trying to write the host key.\n"
1006     "You do not have permission to write to the known-hosts file.");
1007 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1008 yutakakn 2861 } else {
1009 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1010 maya 3003 "An error occurred while trying to write the host key.\n"
1011     "The host key could not be written.");
1012 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1013 yutakakn 2861 }
1014     free(filename);
1015     return;
1016     }
1017    
1018     // ���������T�[�o���L�[����������
1019     if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1020     key.type = KEY_RSA1;
1021     key.bits = pvar->hosts_state.hostkey.bits;
1022     key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1023     key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1024     } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1025     key.type = KEY_RSA;
1026     key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1027     } else { // SSH2 DSA
1028     key.type = KEY_DSA;
1029     key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1030     }
1031    
1032     // �t�@�C��������������
1033     begin_read_host_files(pvar, 0);
1034     do {
1035     int host_index = 0;
1036     int matched = 0;
1037     int keybits = 0;
1038     char FAR *data;
1039     int do_write = 0;
1040     length = amount_written = 0;
1041    
1042     if (!read_host_key(pvar, pvar->ssh_state.hostname, 0, 1)) {
1043     break;
1044     }
1045    
1046     if (data_index == pvar->hosts_state.file_data_index) {
1047     // index ���i������ == ��������������
1048     break;
1049     }
1050    
1051     data = pvar->hosts_state.file_data + data_index;
1052     host_index = eat_spaces(data);
1053    
1054     if (data[host_index] == '#') {
1055     do_write = 1;
1056     }
1057     else {
1058     // �z�X�g������
1059     host_index--;
1060     do {
1061     int negated;
1062    
1063     host_index++;
1064     negated = data[host_index] == '!';
1065    
1066     if (negated) {
1067     host_index++;
1068     if (match_pattern(data + host_index,
1069 maya 3003 pvar->ssh_state.hostname)) {
1070 yutakakn 2861 matched = 0;
1071     // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1072     host_index--;
1073     do {
1074     host_index++;
1075     host_index += eat_to_end_of_pattern(data + host_index);
1076     } while (data[host_index] == ',');
1077     break;
1078     }
1079     }
1080     else if (match_pattern(data + host_index,
1081 maya 3003 pvar->ssh_state.hostname)) {
1082 yutakakn 2861 matched = 1;
1083     }
1084     host_index += eat_to_end_of_pattern(data + host_index);
1085     } while (data[host_index] == ',');
1086    
1087     // �z�X�g�������������v�����L�[����������
1088     if (match_key(pvar, &key)) {
1089     do_write = 1;
1090     }
1091     // �z�X�g������������
1092     else if (!matched) {
1093     do_write = 1;
1094     }
1095     // �z�X�g�������� and �������o�[�W����������
1096     else {
1097     int rsa1_key_bits=0;
1098     rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1099    
1100     if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1101     if (!SSHv1(pvar)) {
1102     do_write = 1;
1103     }
1104     }
1105     else { // �t�@�C�����L�[�� ssh2
1106     if (!SSHv2(pvar)) {
1107     do_write = 1;
1108     }
1109     }
1110     }
1111     }
1112    
1113     // ������������
1114     if (do_write) {
1115     length = pvar->hosts_state.file_data_index - data_index;
1116     amount_written =
1117     _write(fd, pvar->hosts_state.file_data + data_index,
1118 maya 3003 length);
1119 yutakakn 2861
1120     if (amount_written != length) {
1121     goto error1;
1122     }
1123     }
1124     data_index = pvar->hosts_state.file_data_index;
1125     } while (1); // ������������
1126    
1127     error1:
1128     close_result = _close(fd);
1129     if (amount_written != length || close_result == -1) {
1130 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1131 maya 3003 "An error occurred while trying to write the host key.\n"
1132     "The host key could not be written.");
1133 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1134 yutakakn 2861 goto error2;
1135     }
1136    
1137     // �������������t�@�C���������l�[��
1138 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1139 yutakakn 2876 _unlink(buf);
1140     rename(filename, buf);
1141 yutakakn 2861
1142     error2:
1143     _unlink(filename);
1144    
1145     finish_read_host_files(pvar, 0);
1146     }
1147     }
1148    
1149     //
1150 yutakakn 2856 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1151     // ���[�U���m�F�������B
1152     // TODO: finger print���\�����s���B
1153     // (2006.3.25 yutaka)
1154     //
1155 yutakakn 2861 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1156 maya 3003 LPARAM lParam)
1157 yutakakn 2728 {
1158     PTInstVar pvar;
1159 maya 2943 LOGFONT logfont;
1160     HFONT font;
1161 maya 2994 char uimsg[MAX_UIMSG];
1162 yutakakn 2728
1163     switch (msg) {
1164     case WM_INITDIALOG:
1165     pvar = (PTInstVar) lParam;
1166     pvar->hosts_state.hosts_dialog = dlg;
1167     SetWindowLong(dlg, DWL_USER, lParam);
1168    
1169 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1170 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1171     UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1172 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1173 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1174     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1175 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1176 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1177     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1178 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1179 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1180     UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1181 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1182 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1183     UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1184 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1185 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1186     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1187 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1188 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1189     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1190 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1191    
1192 yutakakn 2728 init_hosts_dlg(pvar, dlg);
1193 yutakakn 2856
1194 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1195     GetObject(font, sizeof(LOGFONT), &logfont);
1196 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1197 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1198     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1199     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1200     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1201     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1202     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1203     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1204     }
1205     else {
1206     DlgHostsAddFont = NULL;
1207     }
1208    
1209 yutakakn 2856 // add host check box���`�F�b�N���f�t�H���g������������
1210     SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1211    
1212 yutakakn 2728 return TRUE; /* because we do not set the focus */
1213    
1214     case WM_COMMAND:
1215     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1216    
1217     switch (LOWORD(wParam)) {
1218     case IDC_CONTINUE:
1219     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1220     add_host_key(pvar);
1221     }
1222    
1223 yutakakn 2856 if (SSHv1(pvar)) {
1224     SSH_notify_host_OK(pvar);
1225     } else { // SSH2
1226     // SSH2���������� SSH_notify_host_OK() �������B
1227     }
1228    
1229 yutakakn 2728 pvar->hosts_state.hosts_dialog = NULL;
1230    
1231     EndDialog(dlg, 1);
1232 maya 2943
1233     if (DlgHostsAddFont != NULL) {
1234     DeleteObject(DlgHostsAddFont);
1235     }
1236    
1237 yutakakn 2728 return TRUE;
1238    
1239     case IDCANCEL: /* kill the connection */
1240     pvar->hosts_state.hosts_dialog = NULL;
1241     notify_closed_connection(pvar);
1242     EndDialog(dlg, 0);
1243 maya 2943
1244     if (DlgHostsAddFont != NULL) {
1245     DeleteObject(DlgHostsAddFont);
1246     }
1247    
1248 yutakakn 2728 return TRUE;
1249    
1250     default:
1251     return FALSE;
1252     }
1253    
1254     default:
1255     return FALSE;
1256     }
1257     }
1258    
1259 yutakakn 2861 //
1260     // �u�����������m�F�_�C�A���O������
1261     //
1262     static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1263 maya 3003 LPARAM lParam)
1264 yutakakn 2728 {
1265 yutakakn 2861 PTInstVar pvar;
1266 maya 2943 LOGFONT logfont;
1267     HFONT font;
1268 maya 2994 char uimsg[MAX_UIMSG];
1269 yutakakn 2728
1270 yutakakn 2861 switch (msg) {
1271     case WM_INITDIALOG:
1272     pvar = (PTInstVar) lParam;
1273     pvar->hosts_state.hosts_dialog = dlg;
1274     SetWindowLong(dlg, DWL_USER, lParam);
1275    
1276 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1277 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1278     UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1279 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1280 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1281     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1282 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1283 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1284     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1285 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1286 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1287     UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1288 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1289 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1290     UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1291 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1292 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1293     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1294 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1295 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1296     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1297 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1298    
1299 yutakakn 2861 init_hosts_dlg(pvar, dlg);
1300    
1301 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1302     GetObject(font, sizeof(LOGFONT), &logfont);
1303 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1304 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1305     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1306     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1307     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1308     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1309     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1310     }
1311     else {
1312     DlgHostsReplaceFont = NULL;
1313     }
1314    
1315 yutakakn 2861 // �f�t�H���g���`�F�b�N����������
1316     return TRUE; /* because we do not set the focus */
1317    
1318     case WM_COMMAND:
1319     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1320    
1321     switch (LOWORD(wParam)) {
1322     case IDC_CONTINUE:
1323     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1324     add_host_key(pvar);
1325     delete_different_key(pvar);
1326     }
1327    
1328     if (SSHv1(pvar)) {
1329     SSH_notify_host_OK(pvar);
1330     } else { // SSH2
1331     // SSH2���������� SSH_notify_host_OK() �������B
1332     }
1333    
1334     pvar->hosts_state.hosts_dialog = NULL;
1335    
1336     EndDialog(dlg, 1);
1337 maya 2943
1338     if (DlgHostsReplaceFont != NULL) {
1339     DeleteObject(DlgHostsReplaceFont);
1340     }
1341    
1342 yutakakn 2861 return TRUE;
1343    
1344     case IDCANCEL: /* kill the connection */
1345     pvar->hosts_state.hosts_dialog = NULL;
1346     notify_closed_connection(pvar);
1347     EndDialog(dlg, 0);
1348 maya 2943
1349     if (DlgHostsReplaceFont != NULL) {
1350     DeleteObject(DlgHostsReplaceFont);
1351     }
1352    
1353 yutakakn 2861 return TRUE;
1354    
1355     default:
1356     return FALSE;
1357     }
1358    
1359     default:
1360     return FALSE;
1361 yutakakn 2728 }
1362     }
1363    
1364     void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1365     {
1366     if (pvar->hosts_state.hosts_dialog == NULL) {
1367     HWND cur_active = GetActiveWindow();
1368    
1369     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1370 maya 3003 cur_active != NULL ? cur_active : wnd,
1371     hosts_add_dlg_proc, (LPARAM) pvar);
1372 yutakakn 2728 }
1373     }
1374    
1375     void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1376     {
1377     if (pvar->hosts_state.hosts_dialog == NULL) {
1378     HWND cur_active = GetActiveWindow();
1379    
1380     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1381 maya 3003 cur_active != NULL ? cur_active : wnd,
1382     hosts_replace_dlg_proc, (LPARAM) pvar);
1383 yutakakn 2728 }
1384     }
1385    
1386 yutakakn 2856 //
1387     // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1388     //
1389     // SSH2���������� (2006.3.24 yutaka)
1390     //
1391     BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, Key *key)
1392 yutakakn 2728 {
1393     int found_different_key = 0;
1394    
1395 yutakakn 2856 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1396 yutakakn 2728 if (pvar->hosts_state.prefetched_hostname != NULL
1397 maya 3003 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1398     && match_key(pvar, key)) {
1399 yutakakn 2856
1400     if (SSHv1(pvar)) {
1401     SSH_notify_host_OK(pvar);
1402     } else {
1403     // SSH2���������� SSH_notify_host_OK() �������B
1404     }
1405 yutakakn 2728 return TRUE;
1406     }
1407    
1408 yutakakn 2856 // �������������������������A�������_���t�@�C��������������
1409 yutakakn 2728 if (begin_read_host_files(pvar, 0)) {
1410     do {
1411 yutakakn 2861 if (!read_host_key(pvar, hostname, 0, 0)) {
1412 yutakakn 2728 break;
1413     }
1414    
1415 yutakakn 2856 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1416     if (match_key(pvar, key)) {
1417 yutakakn 2728 finish_read_host_files(pvar, 0);
1418 yutakakn 2859 // ���������G���g�����Q�������A���v�����L�[�������������������B
1419     // SSH2���������������������������B(2006.3.29 yutaka)
1420     if (SSHv1(pvar)) {
1421     SSH_notify_host_OK(pvar);
1422     } else {
1423     // SSH2���������� SSH_notify_host_OK() �������B
1424     }
1425 yutakakn 2728 return TRUE;
1426     } else {
1427 yutakakn 2856 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1428 yutakakn 2728 found_different_key = 1;
1429     }
1430     }
1431 yutakakn 2856 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1432 yutakakn 2728
1433     finish_read_host_files(pvar, 0);
1434     }
1435    
1436 yutakakn 2856
1437     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1438     pvar->hosts_state.hostkey.type = key->type;
1439     if (key->type == KEY_RSA1) { // SSH1
1440     pvar->hosts_state.hostkey.bits = key->bits;
1441     pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1442     pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1443    
1444     } else if (key->type == KEY_RSA) { // SSH2 RSA
1445     pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1446    
1447     } else { // SSH2 DSA
1448     pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1449    
1450     }
1451 yutakakn 2728 free(pvar->hosts_state.prefetched_hostname);
1452     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1453    
1454 yutakapon 3017 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1455     // �������K�v�����������A�����R�[�������X�����B
1456     // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1457     // (2007.10.1 yutaka)
1458 yutakakn 2728 if (found_different_key) {
1459 yutakapon 3017 #if 0
1460 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1461 maya 3003 ID_SSHDIFFERENTHOST, 0);
1462 yutakapon 3017 #else
1463     HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1464     #endif
1465 yutakakn 2728 } else {
1466 yutakapon 3017 #if 0
1467 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1468 maya 3003 ID_SSHUNKNOWNHOST, 0);
1469 yutakapon 3017 #else
1470     HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1471     #endif
1472    
1473 yutakakn 2728 }
1474    
1475     return TRUE;
1476     }
1477    
1478     void HOSTS_notify_disconnecting(PTInstVar pvar)
1479     {
1480     if (pvar->hosts_state.hosts_dialog != NULL) {
1481     PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1482 maya 3003 0);
1483 yutakakn 2728 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1484     EnableWindow(pvar->NotificationWindow, TRUE);
1485     }
1486     }
1487    
1488     void HOSTS_end(PTInstVar pvar)
1489     {
1490     int i;
1491    
1492     free(pvar->hosts_state.prefetched_hostname);
1493 yutakakn 2856 #if 0
1494 yutakakn 2728 free(pvar->hosts_state.key_exp);
1495     free(pvar->hosts_state.key_mod);
1496 yutakakn 2856 #else
1497     init_hostkey(&pvar->hosts_state.hostkey);
1498     #endif
1499 yutakakn 2728
1500     if (pvar->hosts_state.file_names != NULL) {
1501     for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1502     free(pvar->hosts_state.file_names[i]);
1503     }
1504     free(pvar->hosts_state.file_names);
1505     }
1506     }

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