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

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