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 4542 - (hide annotations) (download) (as text)
Wed Jul 27 14:25:26 2011 UTC (12 years, 8 months ago) by doda
File MIME type: text/x-csrc
File size: 51743 byte(s)
/nosecuritywarning 時は SSHFP 検証をしても無駄なので、検証するタイミングを変更。

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

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