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

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