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

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