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 3126 - (hide annotations) (download) (as text)
Mon May 19 08:37:18 2008 UTC (15 years, 10 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/hosts.c
File MIME type: text/x-csrc
File size: 40118 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    
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 maya 3126 static int read_host_key(PTInstVar pvar,
627     char FAR * hostname, unsigned short tcpport,
628 maya 3003 int suppress_errors, int return_always)
629 yutakakn 2728 {
630     int i;
631 yutakakn 2861 int while_flg;
632 yutakakn 2728
633     for (i = 0; hostname[i] != 0; i++) {
634     int ch = hostname[i];
635    
636     if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
637     if (!suppress_errors) {
638 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
639 maya 3003 "The host name contains an invalid character.\n"
640     "This session will be terminated.");
641 maya 2942 notify_fatal_error(pvar, pvar->ts->UIMsg);
642 yutakakn 2728 }
643     return 0;
644     }
645     }
646    
647     if (i == 0) {
648     if (!suppress_errors) {
649 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
650 maya 3003 "The host name should not be empty.\n"
651     "This session will be terminated.");
652 maya 2942 notify_fatal_error(pvar, pvar->ts->UIMsg);
653 yutakakn 2728 }
654     return 0;
655     }
656    
657 yutakakn 2856 #if 0
658 yutakakn 2728 pvar->hosts_state.key_bits = 0;
659     free(pvar->hosts_state.key_exp);
660     pvar->hosts_state.key_exp = NULL;
661     free(pvar->hosts_state.key_mod);
662     pvar->hosts_state.key_mod = NULL;
663 yutakakn 2856 #else
664     // hostkey type is KEY_UNSPEC.
665     init_hostkey(&pvar->hosts_state.hostkey);
666     #endif
667 yutakakn 2728
668     do {
669     if (pvar->hosts_state.file_data == NULL
670 maya 3003 || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
671 yutakakn 2728 char FAR *filename;
672     int keep_going = 1;
673    
674     if (pvar->hosts_state.file_data != NULL) {
675     end_read_file(pvar, suppress_errors);
676     }
677    
678     do {
679     filename =
680 maya 3003 pvar->hosts_state.file_names[pvar->hosts_state.file_num];
681 yutakakn 2728
682     if (filename == NULL) {
683     return 1;
684     } else {
685     pvar->hosts_state.file_num++;
686    
687     if (filename[0] != 0) {
688 maya 3003 if (begin_read_file(pvar, filename, suppress_errors)) {
689 yutakakn 2728 pvar->hosts_state.file_data_index = 0;
690     keep_going = 0;
691     }
692     }
693     }
694     } while (keep_going);
695     }
696    
697     pvar->hosts_state.file_data_index +=
698 maya 3126 check_host_key(pvar, hostname, tcpport,
699 maya 3003 pvar->hosts_state.file_data +
700     pvar->hosts_state.file_data_index);
701 yutakakn 2728
702 yutakakn 2861 if (!return_always) {
703     // �L�����L�[��������������
704     while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
705     }
706     else {
707     while_flg = 0;
708     }
709     } while (while_flg);
710    
711 yutakakn 2728 return 1;
712     }
713    
714     static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
715     {
716     if (pvar->hosts_state.file_data != NULL) {
717     end_read_file(pvar, suppress_errors);
718     }
719     }
720    
721 yutakakn 2856 // �T�[�o�����������O���Aknown_hosts�t�@�C�������z�X�g���J�������������������B
722 maya 3126 void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport)
723 yutakakn 2728 {
724     if (!begin_read_host_files(pvar, 1)) {
725     return;
726     }
727    
728 maya 3126 if (!read_host_key(pvar, hostname, tcpport, 1, 0)) {
729 yutakakn 2728 return;
730     }
731    
732     free(pvar->hosts_state.prefetched_hostname);
733     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
734    
735     finish_read_host_files(pvar, 1);
736     }
737    
738     static BOOL equal_mp_ints(unsigned char FAR * num1,
739 maya 3003 unsigned char FAR * num2)
740 yutakakn 2728 {
741     if (num1 == NULL || num2 == NULL) {
742     return FALSE;
743     } else {
744     uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
745    
746     if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
747     return FALSE; /* different byte lengths */
748     } else {
749     return memcmp(num1 + 2, num2 + 2, bytes) == 0;
750     }
751     }
752     }
753    
754 yutakakn 2856 // ���J����������������������
755     static BOOL match_key(PTInstVar pvar, Key *key)
756 yutakakn 2728 {
757 yutakakn 2856 int bits;
758     unsigned char FAR * exp;
759     unsigned char FAR * mod;
760    
761     if (key->type == KEY_RSA1) { // SSH1 host public key
762     bits = key->bits;
763     exp = key->exp;
764     mod = key->mod;
765    
766     /* just check for equal exponent and modulus */
767     return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
768 maya 3003 && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
769 yutakakn 2856 /*
770     return equal_mp_ints(exp, pvar->hosts_state.key_exp)
771     && equal_mp_ints(mod, pvar->hosts_state.key_mod);
772     */
773    
774     } else if (key->type == KEY_RSA) { // SSH2 RSA host public key
775    
776     return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
777 maya 3003 BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
778     BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
779 yutakakn 2856
780     } else { // // SSH2 DSA host public key
781    
782     return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
783 maya 3003 BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
784     BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
785     BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
786     BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
787 yutakakn 2856
788     }
789    
790 yutakakn 2728 }
791    
792     static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
793     {
794     char buf[1024];
795     char buf2[2048];
796     int i, j;
797     int ch;
798 yutakakn 2857 char *fp;
799 yutakakn 2728
800 yutakakn 2857 // static text�� # �������z�X�g�����u������
801 yutakakn 2728 GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
802     for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
803     buf2[i] = ch;
804     }
805 maya 2992 strncpy_s(buf2 + i, sizeof(buf2) - i,
806 maya 3003 pvar->hosts_state.prefetched_hostname, _TRUNCATE);
807 yutakakn 2728 j = i + strlen(buf2 + i);
808     for (; buf[i] == '#'; i++) {
809     }
810 maya 2992 strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
811 yutakakn 2728
812     SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
813 yutakakn 2857
814     // fingerprint����������
815     fp = key_fingerprint(&pvar->hosts_state.hostkey);
816     SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
817 yutakakn 2728 }
818    
819     static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
820     {
821     int i = 0, j, k;
822     BIGNUM *num = BN_new();
823     int ch;
824    
825     BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
826    
827     do {
828     buf[i] = (char) ((BN_div_word(num, 10)) + '0');
829     i++;
830     } while (!BN_is_zero(num));
831    
832     /* we need to reverse the digits */
833     for (j = 0, k = i - 1; j < k; j++, k--) {
834     ch = buf[j];
835     buf[j] = buf[k];
836     buf[k] = ch;
837     }
838    
839     buf[i] = 0;
840     return i;
841     }
842    
843 yutakakn 2856 //
844     // known_hosts �t�@�C�������������G���g�������������B
845     //
846 yutakakn 2728 static char FAR *format_host_key(PTInstVar pvar)
847     {
848     int host_len = strlen(pvar->hosts_state.prefetched_hostname);
849 yutakakn 2856 char *result = NULL;
850     int index;
851     enum hostkey_type type = pvar->hosts_state.hostkey.type;
852    
853     if (type == KEY_RSA1) {
854 maya 2992 int result_len = host_len + 50 +
855 maya 3003 get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
856     get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
857 maya 2992 result = (char FAR *) malloc(result_len);
858 yutakakn 2728
859 maya 2992 strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
860 yutakakn 2856 index = host_len;
861 yutakakn 2728
862 maya 2992 _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
863 maya 3003 " %d ", pvar->hosts_state.hostkey.bits);
864 yutakakn 2856 index += strlen(result + index);
865     index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
866     result[index] = ' ';
867     index++;
868     index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
869 maya 2992 strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
870 yutakakn 2728
871 yutakakn 2856 } else if (type == KEY_RSA || type == KEY_DSA) {
872     Key *key = &pvar->hosts_state.hostkey;
873     char *blob = NULL;
874     int blen, uulen, msize;
875     char *uu = NULL;
876     int n;
877    
878     key_to_blob(key, &blob, &blen);
879     uulen = 2 * blen;
880     uu = malloc(uulen);
881     if (uu == NULL) {
882     goto error;
883     }
884     n = uuencode(blob, blen, uu, uulen);
885     if (n > 0) {
886     msize = host_len + 50 + uulen;
887     result = malloc(msize);
888     if (result == NULL) {
889     goto error;
890     }
891    
892     // setup
893 maya 2992 _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
894 maya 3003 pvar->hosts_state.prefetched_hostname,
895     get_sshname_from_key(key),
896     uu);
897 yutakakn 2856 }
898     error:
899     if (blob != NULL)
900     free(blob);
901     if (uu != NULL)
902     free(uu);
903    
904     } else {
905     return NULL;
906    
907     }
908    
909 yutakakn 2728 return result;
910     }
911    
912     static void add_host_key(PTInstVar pvar)
913     {
914     char FAR *name = pvar->hosts_state.file_names[0];
915    
916 maya 2879 if (name == NULL || name[0] == 0) {
917 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
918 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
919     "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
920 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
921 yutakakn 2728 } else {
922     char FAR *keydata = format_host_key(pvar);
923     int length = strlen(keydata);
924 maya 2879 int fd;
925 yutakakn 2728 int amount_written;
926     int close_result;
927 maya 2879 char buf[FILENAME_MAX];
928 yutakakn 2728
929 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
930     fd = _open(buf,
931 maya 3003 _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
932     _S_IREAD | _S_IWRITE);
933 yutakakn 2728 if (fd == -1) {
934     if (errno == EACCES) {
935 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
936 maya 3003 "An error occurred while trying to write the host key.\n"
937     "You do not have permission to write to the known-hosts file.");
938 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
939 yutakakn 2728 } else {
940 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
941 maya 3003 "An error occurred while trying to write the host key.\n"
942     "The host key could not be written.");
943 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
944 yutakakn 2728 }
945     return;
946     }
947    
948     amount_written = _write(fd, keydata, length);
949     free(keydata);
950     close_result = _close(fd);
951    
952     if (amount_written != length || close_result == -1) {
953 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
954 maya 3003 "An error occurred while trying to write the host key.\n"
955     "The host key could not be written.");
956 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
957 yutakakn 2728 }
958     }
959     }
960    
961 yutakakn 2861 static char FAR *copy_mp_int(char FAR * num)
962     {
963     int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
964     char FAR *result = (char FAR *) malloc(len);
965    
966     if (result != NULL) {
967     memcpy(result, num, len);
968     }
969    
970     return result;
971     }
972    
973 yutakakn 2856 //
974 yutakakn 2861 // �����z�X�g�����e���������L�[����������
975     // add_host_key ����������������
976     //
977     static void delete_different_key(PTInstVar pvar)
978     {
979     char FAR *name = pvar->hosts_state.file_names[0];
980    
981 maya 2879 if (name == NULL || name[0] == 0) {
982 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
983 maya 3003 "The host and its key cannot be added, because no known-hosts file has been specified.\n"
984     "Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
985 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
986 yutakakn 2861 }
987     else {
988     Key key; // ���������z�X�g���L�[
989 yutakakn 2876 int length;
990 yutakakn 2861 char filename[L_tmpnam];
991     int fd;
992     int amount_written = 0;
993     int close_result;
994     int data_index = 0;
995 maya 2879 char buf[FILENAME_MAX];
996 yutakakn 2861
997     // �������������t�@�C�����J��
998     tmpnam(filename);
999 maya 3003 fd = _open(filename,
1000     _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1001     _S_IREAD | _S_IWRITE);
1002 yutakakn 2861
1003     if (fd == -1) {
1004     if (errno == EACCES) {
1005 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1006 maya 3003 "An error occurred while trying to write the host key.\n"
1007     "You do not have permission to write to the known-hosts file.");
1008 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1009 yutakakn 2861 } else {
1010 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1011 maya 3003 "An error occurred while trying to write the host key.\n"
1012     "The host key could not be written.");
1013 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1014 yutakakn 2861 }
1015     free(filename);
1016     return;
1017     }
1018    
1019     // ���������T�[�o���L�[����������
1020     if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1021     key.type = KEY_RSA1;
1022     key.bits = pvar->hosts_state.hostkey.bits;
1023     key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1024     key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1025     } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1026     key.type = KEY_RSA;
1027     key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1028     } else { // SSH2 DSA
1029     key.type = KEY_DSA;
1030     key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1031     }
1032    
1033     // �t�@�C��������������
1034     begin_read_host_files(pvar, 0);
1035     do {
1036     int host_index = 0;
1037     int matched = 0;
1038     int keybits = 0;
1039     char FAR *data;
1040     int do_write = 0;
1041     length = amount_written = 0;
1042    
1043 maya 3126 if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1044 yutakakn 2861 break;
1045     }
1046    
1047     if (data_index == pvar->hosts_state.file_data_index) {
1048     // index ���i������ == ��������������
1049     break;
1050     }
1051    
1052     data = pvar->hosts_state.file_data + data_index;
1053     host_index = eat_spaces(data);
1054    
1055     if (data[host_index] == '#') {
1056     do_write = 1;
1057     }
1058     else {
1059     // �z�X�g������
1060     host_index--;
1061     do {
1062     int negated;
1063    
1064     host_index++;
1065     negated = data[host_index] == '!';
1066    
1067     if (negated) {
1068     host_index++;
1069     if (match_pattern(data + host_index,
1070 maya 3003 pvar->ssh_state.hostname)) {
1071 yutakakn 2861 matched = 0;
1072     // �����o�[�W�����`�F�b�N�������� host_index ���i��������������
1073     host_index--;
1074     do {
1075     host_index++;
1076     host_index += eat_to_end_of_pattern(data + host_index);
1077     } while (data[host_index] == ',');
1078     break;
1079     }
1080     }
1081     else if (match_pattern(data + host_index,
1082 maya 3003 pvar->ssh_state.hostname)) {
1083 yutakakn 2861 matched = 1;
1084     }
1085     host_index += eat_to_end_of_pattern(data + host_index);
1086     } while (data[host_index] == ',');
1087    
1088     // �z�X�g�������������v�����L�[����������
1089     if (match_key(pvar, &key)) {
1090     do_write = 1;
1091     }
1092     // �z�X�g������������
1093     else if (!matched) {
1094     do_write = 1;
1095     }
1096     // �z�X�g�������� and �������o�[�W����������
1097     else {
1098     int rsa1_key_bits=0;
1099     rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1100    
1101     if (rsa1_key_bits > 0) { // �t�@�C�����L�[�� ssh1
1102     if (!SSHv1(pvar)) {
1103     do_write = 1;
1104     }
1105     }
1106     else { // �t�@�C�����L�[�� ssh2
1107     if (!SSHv2(pvar)) {
1108     do_write = 1;
1109     }
1110     }
1111     }
1112     }
1113    
1114     // ������������
1115     if (do_write) {
1116     length = pvar->hosts_state.file_data_index - data_index;
1117     amount_written =
1118     _write(fd, pvar->hosts_state.file_data + data_index,
1119 maya 3003 length);
1120 yutakakn 2861
1121     if (amount_written != length) {
1122     goto error1;
1123     }
1124     }
1125     data_index = pvar->hosts_state.file_data_index;
1126     } while (1); // ������������
1127    
1128     error1:
1129     close_result = _close(fd);
1130     if (amount_written != length || close_result == -1) {
1131 maya 2994 UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1132 maya 3003 "An error occurred while trying to write the host key.\n"
1133     "The host key could not be written.");
1134 maya 2942 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1135 yutakakn 2861 goto error2;
1136     }
1137    
1138     // �������������t�@�C���������l�[��
1139 maya 2879 get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1140 yutakakn 2876 _unlink(buf);
1141     rename(filename, buf);
1142 yutakakn 2861
1143     error2:
1144     _unlink(filename);
1145    
1146     finish_read_host_files(pvar, 0);
1147     }
1148     }
1149    
1150     //
1151 yutakakn 2856 // Unknown host���z�X�g���J���� known_hosts �t�@�C����������������������
1152     // ���[�U���m�F�������B
1153     // TODO: finger print���\�����s���B
1154     // (2006.3.25 yutaka)
1155     //
1156 yutakakn 2861 static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1157 maya 3003 LPARAM lParam)
1158 yutakakn 2728 {
1159     PTInstVar pvar;
1160 maya 2943 LOGFONT logfont;
1161     HFONT font;
1162 maya 2994 char uimsg[MAX_UIMSG];
1163 yutakakn 2728
1164     switch (msg) {
1165     case WM_INITDIALOG:
1166     pvar = (PTInstVar) lParam;
1167     pvar->hosts_state.hosts_dialog = dlg;
1168     SetWindowLong(dlg, DWL_USER, lParam);
1169    
1170 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1171 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1172     UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1173 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1174 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1175     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1176 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1177 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1178     UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1179 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1180 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1181     UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1182 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1183 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1184     UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1185 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1186 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1187     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1188 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1189 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1190     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1191 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1192    
1193 yutakakn 2728 init_hosts_dlg(pvar, dlg);
1194 yutakakn 2856
1195 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1196     GetObject(font, sizeof(LOGFONT), &logfont);
1197 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1198 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1199     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1200     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1201     SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1202     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1203     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1204     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1205     }
1206     else {
1207     DlgHostsAddFont = NULL;
1208     }
1209    
1210 yutakakn 2856 // add host check box���`�F�b�N���f�t�H���g������������
1211     SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1212    
1213 yutakakn 2728 return TRUE; /* because we do not set the focus */
1214    
1215     case WM_COMMAND:
1216     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1217    
1218     switch (LOWORD(wParam)) {
1219     case IDC_CONTINUE:
1220     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1221     add_host_key(pvar);
1222     }
1223    
1224 yutakakn 2856 if (SSHv1(pvar)) {
1225     SSH_notify_host_OK(pvar);
1226     } else { // SSH2
1227     // SSH2���������� SSH_notify_host_OK() �������B
1228     }
1229    
1230 yutakakn 2728 pvar->hosts_state.hosts_dialog = NULL;
1231    
1232     EndDialog(dlg, 1);
1233 maya 2943
1234     if (DlgHostsAddFont != NULL) {
1235     DeleteObject(DlgHostsAddFont);
1236     }
1237    
1238 yutakakn 2728 return TRUE;
1239    
1240     case IDCANCEL: /* kill the connection */
1241     pvar->hosts_state.hosts_dialog = NULL;
1242     notify_closed_connection(pvar);
1243     EndDialog(dlg, 0);
1244 maya 2943
1245     if (DlgHostsAddFont != NULL) {
1246     DeleteObject(DlgHostsAddFont);
1247     }
1248    
1249 yutakakn 2728 return TRUE;
1250    
1251     default:
1252     return FALSE;
1253     }
1254    
1255     default:
1256     return FALSE;
1257     }
1258     }
1259    
1260 yutakakn 2861 //
1261     // �u�����������m�F�_�C�A���O������
1262     //
1263     static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1264 maya 3003 LPARAM lParam)
1265 yutakakn 2728 {
1266 yutakakn 2861 PTInstVar pvar;
1267 maya 2943 LOGFONT logfont;
1268     HFONT font;
1269 maya 2994 char uimsg[MAX_UIMSG];
1270 yutakakn 2728
1271 yutakakn 2861 switch (msg) {
1272     case WM_INITDIALOG:
1273     pvar = (PTInstVar) lParam;
1274     pvar->hosts_state.hosts_dialog = dlg;
1275     SetWindowLong(dlg, DWL_USER, lParam);
1276    
1277 maya 2937 // �����E�u���������� init_hosts_dlg �����������������A�����O���Z�b�g�����K�v������
1278 maya 2994 GetWindowText(dlg, uimsg, sizeof(uimsg));
1279     UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1280 maya 2937 SetWindowText(dlg, pvar->ts->UIMsg);
1281 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1282     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1283 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1284 maya 2994 GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1285     UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1286 maya 2937 SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1287 maya 2994 GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1288     UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1289 maya 2937 SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1290 maya 2994 GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1291     UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1292 maya 2937 SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1293 maya 2994 GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1294     UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1295 maya 2937 SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1296 maya 2994 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1297     UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1298 maya 2937 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1299    
1300 yutakakn 2861 init_hosts_dlg(pvar, dlg);
1301    
1302 maya 2943 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1303     GetObject(font, sizeof(LOGFONT), &logfont);
1304 maya 2946 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1305 maya 2943 SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1306     SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1307     SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1308     SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1309     SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1310     SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1311     }
1312     else {
1313     DlgHostsReplaceFont = NULL;
1314     }
1315    
1316 yutakakn 2861 // �f�t�H���g���`�F�b�N����������
1317     return TRUE; /* because we do not set the focus */
1318    
1319     case WM_COMMAND:
1320     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1321    
1322     switch (LOWORD(wParam)) {
1323     case IDC_CONTINUE:
1324     if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1325     add_host_key(pvar);
1326     delete_different_key(pvar);
1327     }
1328    
1329     if (SSHv1(pvar)) {
1330     SSH_notify_host_OK(pvar);
1331     } else { // SSH2
1332     // SSH2���������� SSH_notify_host_OK() �������B
1333     }
1334    
1335     pvar->hosts_state.hosts_dialog = NULL;
1336    
1337     EndDialog(dlg, 1);
1338 maya 2943
1339     if (DlgHostsReplaceFont != NULL) {
1340     DeleteObject(DlgHostsReplaceFont);
1341     }
1342    
1343 yutakakn 2861 return TRUE;
1344    
1345     case IDCANCEL: /* kill the connection */
1346     pvar->hosts_state.hosts_dialog = NULL;
1347     notify_closed_connection(pvar);
1348     EndDialog(dlg, 0);
1349 maya 2943
1350     if (DlgHostsReplaceFont != NULL) {
1351     DeleteObject(DlgHostsReplaceFont);
1352     }
1353    
1354 yutakakn 2861 return TRUE;
1355    
1356     default:
1357     return FALSE;
1358     }
1359    
1360     default:
1361     return FALSE;
1362 yutakakn 2728 }
1363     }
1364    
1365     void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1366     {
1367     if (pvar->hosts_state.hosts_dialog == NULL) {
1368     HWND cur_active = GetActiveWindow();
1369    
1370     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1371 maya 3003 cur_active != NULL ? cur_active : wnd,
1372     hosts_add_dlg_proc, (LPARAM) pvar);
1373 yutakakn 2728 }
1374     }
1375    
1376     void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1377     {
1378     if (pvar->hosts_state.hosts_dialog == NULL) {
1379     HWND cur_active = GetActiveWindow();
1380    
1381     DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1382 maya 3003 cur_active != NULL ? cur_active : wnd,
1383     hosts_replace_dlg_proc, (LPARAM) pvar);
1384 yutakakn 2728 }
1385     }
1386    
1387 yutakakn 2856 //
1388     // �T�[�o�����������������z�X�g���J�������������`�F�b�N����
1389     //
1390     // SSH2���������� (2006.3.24 yutaka)
1391     //
1392 maya 3126 BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1393 yutakakn 2728 {
1394     int found_different_key = 0;
1395    
1396 yutakakn 2856 // ������ known_hosts �t�@�C�������z�X�g���J�����������������������A���������r�����B
1397 yutakakn 2728 if (pvar->hosts_state.prefetched_hostname != NULL
1398 maya 3003 && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1399     && match_key(pvar, key)) {
1400 yutakakn 2856
1401     if (SSHv1(pvar)) {
1402     SSH_notify_host_OK(pvar);
1403     } else {
1404     // SSH2���������� SSH_notify_host_OK() �������B
1405     }
1406 yutakakn 2728 return TRUE;
1407     }
1408    
1409 yutakakn 2856 // �������������������������A�������_���t�@�C��������������
1410 yutakakn 2728 if (begin_read_host_files(pvar, 0)) {
1411     do {
1412 maya 3126 if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1413 yutakakn 2728 break;
1414     }
1415    
1416 yutakakn 2856 if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1417     if (match_key(pvar, key)) {
1418 yutakakn 2728 finish_read_host_files(pvar, 0);
1419 yutakakn 2859 // ���������G���g�����Q�������A���v�����L�[�������������������B
1420     // SSH2���������������������������B(2006.3.29 yutaka)
1421     if (SSHv1(pvar)) {
1422     SSH_notify_host_OK(pvar);
1423     } else {
1424     // SSH2���������� SSH_notify_host_OK() �������B
1425     }
1426 yutakakn 2728 return TRUE;
1427     } else {
1428 yutakakn 2856 // �L�[�� known_hosts ���������������A�L�[�����e���������B
1429 yutakakn 2728 found_different_key = 1;
1430     }
1431     }
1432 yutakakn 2856 } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // �L�[�����������������������[�v����
1433 yutakakn 2728
1434     finish_read_host_files(pvar, 0);
1435     }
1436    
1437 yutakakn 2856
1438     // known_hosts �������������L�[���������t�@�C�������������������A�������������������B
1439     pvar->hosts_state.hostkey.type = key->type;
1440     if (key->type == KEY_RSA1) { // SSH1
1441     pvar->hosts_state.hostkey.bits = key->bits;
1442     pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1443     pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1444    
1445     } else if (key->type == KEY_RSA) { // SSH2 RSA
1446     pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1447    
1448     } else { // SSH2 DSA
1449     pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1450    
1451     }
1452 yutakakn 2728 free(pvar->hosts_state.prefetched_hostname);
1453     pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1454    
1455 yutakapon 3017 // known_hosts�_�C�A���O�������I���\�������A�������_�����������[�U���m�F
1456     // �������K�v�����������A�����R�[�������X�����B
1457     // ����������known_hosts���m�F�����������A�T�[�o�����[�U���������������������������������B
1458     // (2007.10.1 yutaka)
1459 yutakakn 2728 if (found_different_key) {
1460 yutakapon 3017 #if 0
1461 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1462 maya 3003 ID_SSHDIFFERENTHOST, 0);
1463 yutakapon 3017 #else
1464     HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1465     #endif
1466 yutakakn 2728 } else {
1467 yutakapon 3017 #if 0
1468 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND,
1469 maya 3003 ID_SSHUNKNOWNHOST, 0);
1470 yutakapon 3017 #else
1471     HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1472     #endif
1473    
1474 yutakakn 2728 }
1475    
1476     return TRUE;
1477     }
1478    
1479     void HOSTS_notify_disconnecting(PTInstVar pvar)
1480     {
1481     if (pvar->hosts_state.hosts_dialog != NULL) {
1482     PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1483 maya 3003 0);
1484 yutakakn 2728 /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1485     EnableWindow(pvar->NotificationWindow, TRUE);
1486     }
1487     }
1488    
1489     void HOSTS_end(PTInstVar pvar)
1490     {
1491     int i;
1492    
1493     free(pvar->hosts_state.prefetched_hostname);
1494 yutakakn 2856 #if 0
1495 yutakakn 2728 free(pvar->hosts_state.key_exp);
1496     free(pvar->hosts_state.key_mod);
1497 yutakakn 2856 #else
1498     init_hostkey(&pvar->hosts_state.hostkey);
1499     #endif
1500 yutakakn 2728
1501     if (pvar->hosts_state.file_names != NULL) {
1502     for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1503     free(pvar->hosts_state.file_names[i]);
1504     }
1505     free(pvar->hosts_state.file_names);
1506     }
1507     }

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