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

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