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

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