Develop and Download Open Source Software

Browse Subversion Repository

Diff of /trunk/ttssh2/ttxssh/hosts.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3221 by maya, Tue Mar 24 09:37:20 2009 UTC revision 3227 by maya, Tue Mar 24 15:10:33 2009 UTC
# Line 1  Line 1 
1  /*  /*
2  Copyright (c) 1998-2001, Robert O'Callahan  Copyright (c) 1998-2001, Robert O'Callahan
3  All rights reserved.  All rights reserved.
4    
5  Redistribution and use in source and binary forms, with or without modification,  Redistribution and use in source and binary forms, with or without modification,
6  are permitted provided that the following conditions are met:  are permitted provided that the following conditions are met:
7    
8  Redistributions of source code must retain the above copyright notice, this list of  Redistributions of source code must retain the above copyright notice, this list of
9  conditions and the following disclaimer.  conditions and the following disclaimer.
10    
11  Redistributions in binary form must reproduce the above copyright notice, this list  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  of conditions and the following disclaimer in the documentation and/or other materials
13  provided with the distribution.  provided with the distribution.
14    
15  The name of Robert O'Callahan may not be used to endorse or promote products derived from  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.  this software without specific prior written permission.
17    
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND  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  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  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,  THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF  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)  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,  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  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.  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */  */
28    
29  /*  /*
30  This code is copyright (C) 1998-1999 Robert O'Callahan.  This code is copyright (C) 1998-1999 Robert O'Callahan.
31  See LICENSE.TXT for the license.  See LICENSE.TXT for the license.
32  */  */
33    
34  #include "ttxssh.h"  #include "ttxssh.h"
35  #include "util.h"  #include "util.h"
36  #include "resource.h"  #include "resource.h"
37  #include "matcher.h"  #include "matcher.h"
38  #include "ssh.h"  #include "ssh.h"
39  #include "hosts.h"  #include "hosts.h"
40    
41  #include <openssl/bn.h>  #include <openssl/bn.h>
42  #include <openssl/evp.h>  #include <openssl/evp.h>
43  #include <openssl/rsa.h>  #include <openssl/rsa.h>
44  #include <openssl/dsa.h>  #include <openssl/dsa.h>
45    
46  #include <fcntl.h>  #include <fcntl.h>
47  #include <io.h>  #include <io.h>
48  #include <errno.h>  #include <errno.h>
49  #include <sys/stat.h>  #include <sys/stat.h>
50  #include <direct.h>  #include <direct.h>
51    
52  static HFONT DlgHostsAddFont;  static HFONT DlgHostsAddFont;
53  static HFONT DlgHostsReplaceFont;  static HFONT DlgHostsReplaceFont;
54    
55  // BASE64構成文字列(ここでは'='は含まれていない)  // BASE64構成文字列(ここでは'='は含まれていない)
56  static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57    
58    
59  // ホストキーの初期化 (2006.3.21 yutaka)  // ホストキーの初期化 (2006.3.21 yutaka)
60  static void init_hostkey(Key *key)  static void init_hostkey(Key *key)
61  {  {
62          key->type = KEY_UNSPEC;          key->type = KEY_UNSPEC;
63    
64          // SSH1          // SSH1
65          key->bits = 0;          key->bits = 0;
66          if (key->exp != NULL) {          if (key->exp != NULL) {
67                  free(key->exp);                  free(key->exp);
68                  key->exp = NULL;                  key->exp = NULL;
69          }          }
70          if (key->mod != NULL) {          if (key->mod != NULL) {
71                  free(key->mod);                  free(key->mod);
72                  key->mod = NULL;                  key->mod = NULL;
73          }          }
74    
75          // SSH2          // SSH2
76          if (key->dsa != NULL) {          if (key->dsa != NULL) {
77                  DSA_free(key->dsa);                  DSA_free(key->dsa);
78                  key->dsa = NULL;                  key->dsa = NULL;
79          }          }
80          if (key->rsa != NULL) {          if (key->rsa != NULL) {
81                  RSA_free(key->rsa);                  RSA_free(key->rsa);
82                  key->rsa = NULL;                  key->rsa = NULL;
83          }          }
84  }  }
85    
86    
87  static char FAR *FAR * parse_multi_path(char FAR * buf)  static char FAR *FAR * parse_multi_path(char FAR * buf)
88  {  {
89          int i;          int i;
90          int ch;          int ch;
91          int num_paths = 1;          int num_paths = 1;
92          char FAR *FAR * result;          char FAR *FAR * result;
93          int last_path_index;          int last_path_index;
94    
95          for (i = 0; (ch = buf[i]) != 0; i++) {          for (i = 0; (ch = buf[i]) != 0; i++) {
96                  if (ch == ';') {                  if (ch == ';') {
97                          num_paths++;                          num_paths++;
98                  }                  }
99          }          }
100    
101          result =          result =
102                  (char FAR * FAR *) malloc(sizeof(char FAR *) * (num_paths + 1));                  (char FAR * FAR *) malloc(sizeof(char FAR *) * (num_paths + 1));
103    
104          last_path_index = 0;          last_path_index = 0;
105          num_paths = 0;          num_paths = 0;
106          for (i = 0; (ch = buf[i]) != 0; i++) {          for (i = 0; (ch = buf[i]) != 0; i++) {
107                  if (ch == ';') {                  if (ch == ';') {
108                          buf[i] = 0;                          buf[i] = 0;
109                          result[num_paths] = _strdup(buf + last_path_index);                          result[num_paths] = _strdup(buf + last_path_index);
110                          num_paths++;                          num_paths++;
111                          buf[i] = ch;                          buf[i] = ch;
112                          last_path_index = i + 1;                          last_path_index = i + 1;
113                  }                  }
114          }          }
115          if (i > last_path_index) {          if (i > last_path_index) {
116                  result[num_paths] = _strdup(buf + last_path_index);                  result[num_paths] = _strdup(buf + last_path_index);
117                  num_paths++;                  num_paths++;
118          }          }
119          result[num_paths] = NULL;          result[num_paths] = NULL;
120          return result;          return result;
121  }  }
122    
123  void HOSTS_init(PTInstVar pvar)  void HOSTS_init(PTInstVar pvar)
124  {  {
125          pvar->hosts_state.prefetched_hostname = NULL;          pvar->hosts_state.prefetched_hostname = NULL;
126  #if 0  #if 0
127          pvar->hosts_state.key_exp = NULL;          pvar->hosts_state.key_exp = NULL;
128          pvar->hosts_state.key_mod = NULL;          pvar->hosts_state.key_mod = NULL;
129  #else  #else
130          init_hostkey(&pvar->hosts_state.hostkey);          init_hostkey(&pvar->hosts_state.hostkey);
131  #endif  #endif
132          pvar->hosts_state.hosts_dialog = NULL;          pvar->hosts_state.hosts_dialog = NULL;
133          pvar->hosts_state.file_names = NULL;          pvar->hosts_state.file_names = NULL;
134  }  }
135    
136  void HOSTS_open(PTInstVar pvar)  void HOSTS_open(PTInstVar pvar)
137  {  {
138          pvar->hosts_state.file_names =          pvar->hosts_state.file_names =
139                  parse_multi_path(pvar->session_settings.KnownHostsFiles);                  parse_multi_path(pvar->session_settings.KnownHostsFiles);
140  }  }
141    
142  //  //
143  // known_hostsファイルの内容をすべて pvar->hosts_state.file_data へ読み込む  // known_hostsファイルの内容をすべて pvar->hosts_state.file_data へ読み込む
144  //  //
145  static int begin_read_file(PTInstVar pvar, char FAR * name,  static int begin_read_file(PTInstVar pvar, char FAR * name,
146                             int suppress_errors)                             int suppress_errors)
147  {  {
148          int fd;          int fd;
149          int length;          int length;
150          int amount_read;          int amount_read;
151          char buf[2048];          char buf[2048];
152    
153          get_teraterm_dir_relative_name(buf, sizeof(buf), name);          get_teraterm_dir_relative_name(buf, sizeof(buf), name);
154          fd = _open(buf, _O_RDONLY | _O_SEQUENTIAL | _O_BINARY);          fd = _open(buf, _O_RDONLY | _O_SEQUENTIAL | _O_BINARY);
155          if (fd == -1) {          if (fd == -1) {
156                  if (!suppress_errors) {                  if (!suppress_errors) {
157                          if (errno == ENOENT) {                          if (errno == ENOENT) {
158                                  UTIL_get_lang_msg("MSG_HOSTS_READ_ENOENT_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_READ_ENOENT_ERROR", pvar,
159                                                    "An error occurred while trying to read a known_hosts file.\n"                                                    "An error occurred while trying to read a known_hosts file.\n"
160                                                    "The specified filename does not exist.");                                                    "The specified filename does not exist.");
161                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
162                          } else {                          } else {
163                                  UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
164                                                    "An error occurred while trying to read a known_hosts file.");                                                    "An error occurred while trying to read a known_hosts file.");
165                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
166                          }                          }
167                  }                  }
168                  return 0;                  return 0;
169          }          }
170    
171          length = (int) _lseek(fd, 0, SEEK_END);          length = (int) _lseek(fd, 0, SEEK_END);
172          _lseek(fd, 0, SEEK_SET);          _lseek(fd, 0, SEEK_SET);
173    
174          if (length >= 0 && length < 0x7FFFFFFF) {          if (length >= 0 && length < 0x7FFFFFFF) {
175                  pvar->hosts_state.file_data = malloc(length + 1);                  pvar->hosts_state.file_data = malloc(length + 1);
176                  if (pvar->hosts_state.file_data == NULL) {                  if (pvar->hosts_state.file_data == NULL) {
177                          if (!suppress_errors) {                          if (!suppress_errors) {
178                                  UTIL_get_lang_msg("MSG_HOSTS_ALLOC_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_ALLOC_ERROR", pvar,
179                                                    "Memory ran out while trying to allocate space to read a known_hosts file.");                                                    "Memory ran out while trying to allocate space to read a known_hosts file.");
180                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
181                          }                          }
182                          _close(fd);                          _close(fd);
183                          return 0;                          return 0;
184                  }                  }
185          } else {          } else {
186                  if (!suppress_errors) {                  if (!suppress_errors) {
187                          UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,                          UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
188                                            "An error occurred while trying to read a known_hosts file.");                                            "An error occurred while trying to read a known_hosts file.");
189                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);
190                  }                  }
191                  _close(fd);                  _close(fd);
192                  return 0;                  return 0;
193          }          }
194    
195          amount_read = _read(fd, pvar->hosts_state.file_data, length);          amount_read = _read(fd, pvar->hosts_state.file_data, length);
196          pvar->hosts_state.file_data[length] = 0;          pvar->hosts_state.file_data[length] = 0;
197    
198          _close(fd);          _close(fd);
199    
200          if (amount_read != length) {          if (amount_read != length) {
201                  if (!suppress_errors) {                  if (!suppress_errors) {
202                          UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,                          UTIL_get_lang_msg("MSG_HOSTS_READ_ERROR", pvar,
203                                            "An error occurred while trying to read a known_hosts file.");                                            "An error occurred while trying to read a known_hosts file.");
204                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);
205                  }                  }
206                  free(pvar->hosts_state.file_data);                  free(pvar->hosts_state.file_data);
207                  pvar->hosts_state.file_data = NULL;                  pvar->hosts_state.file_data = NULL;
208                  return 0;                  return 0;
209          } else {          } else {
210                  return 1;                  return 1;
211          }          }
212  }  }
213    
214  static int end_read_file(PTInstVar pvar, int suppress_errors)  static int end_read_file(PTInstVar pvar, int suppress_errors)
215  {  {
216          free(pvar->hosts_state.file_data);          free(pvar->hosts_state.file_data);
217          pvar->hosts_state.file_data = NULL;          pvar->hosts_state.file_data = NULL;
218          return 1;          return 1;
219  }  }
220    
221  static int begin_read_host_files(PTInstVar pvar, int suppress_errors)  static int begin_read_host_files(PTInstVar pvar, int suppress_errors)
222  {  {
223          pvar->hosts_state.file_num = 0;          pvar->hosts_state.file_num = 0;
224          pvar->hosts_state.file_data = NULL;          pvar->hosts_state.file_data = NULL;
225          return 1;          return 1;
226  }  }
227    
228  // MIME64の文字列をスキップする  // MIME64の文字列をスキップする
229  static int eat_base64(char FAR * data)  static int eat_base64(char FAR * data)
230  {  {
231          int index = 0;          int index = 0;
232          int ch;          int ch;
233    
234          for (;;) {          for (;;) {
235                  ch = data[index];                  ch = data[index];
236                  if (ch == '=' || strchr(base64, ch)) {                  if (ch == '=' || strchr(base64, ch)) {
237                          // BASE64の構成文字が見つかったら index を進める                          // BASE64の構成文字が見つかったら index を進める
238                          index++;                          index++;
239                  } else {                  } else {
240                          break;                          break;
241                  }                  }
242          }          }
243    
244          return index;          return index;
245  }  }
246    
247  static int eat_spaces(char FAR * data)  static int eat_spaces(char FAR * data)
248  {  {
249          int index = 0;          int index = 0;
250          int ch;          int ch;
251    
252          while ((ch = data[index]) == ' ' || ch == '\t') {          while ((ch = data[index]) == ' ' || ch == '\t') {
253                  index++;                  index++;
254          }          }
255          return index;          return index;
256  }  }
257    
258  static int eat_digits(char FAR * data)  static int eat_digits(char FAR * data)
259  {  {
260          int index = 0;          int index = 0;
261          int ch;          int ch;
262    
263          while ((ch = data[index]) >= '0' && ch <= '9') {          while ((ch = data[index]) >= '0' && ch <= '9') {
264                  index++;                  index++;
265          }          }
266          return index;          return index;
267  }  }
268    
269  static int eat_to_end_of_line(char FAR * data)  static int eat_to_end_of_line(char FAR * data)
270  {  {
271          int index = 0;          int index = 0;
272          int ch;          int ch;
273    
274          while ((ch = data[index]) != '\n' && ch != '\r' && ch != 0) {          while ((ch = data[index]) != '\n' && ch != '\r' && ch != 0) {
275                  index++;                  index++;
276          }          }
277    
278          while ((ch = data[index]) == '\n' || ch == '\r') {          while ((ch = data[index]) == '\n' || ch == '\r') {
279                  index++;                  index++;
280          }          }
281    
282          return index;          return index;
283  }  }
284    
285  static int eat_to_end_of_pattern(char FAR * data)  static int eat_to_end_of_pattern(char FAR * data)
286  {  {
287          int index = 0;          int index = 0;
288          int ch;          int ch;
289    
290          while (ch = data[index], is_pattern_char(ch)) {          while (ch = data[index], is_pattern_char(ch)) {
291                  index++;                  index++;
292          }          }
293    
294          return index;          return index;
295  }  }
296    
297  //  //
298  // BASE64デコード処理を行う。(rfc1521)  // BASE64デコード処理を行う。(rfc1521)
299  // srcバッファは null-terminate している必要あり。  // srcバッファは null-terminate している必要あり。
300  //  //
301  static int uudecode(unsigned char *src, int srclen, unsigned char *target, int targsize)  static int uudecode(unsigned char *src, int srclen, unsigned char *target, int targsize)
302  {  {
303          char pad = '=';          char pad = '=';
304          int tarindex, state, ch;          int tarindex, state, ch;
305          char *pos;          char *pos;
306    
307          state = 0;          state = 0;
308          tarindex = 0;          tarindex = 0;
309    
310          while ((ch = *src++) != '\0') {          while ((ch = *src++) != '\0') {
311                  if (isspace(ch))        /* Skip whitespace anywhere. */                  if (isspace(ch))        /* Skip whitespace anywhere. */
312                          continue;                          continue;
313    
314                  if (ch == pad)                  if (ch == pad)
315                          break;                          break;
316    
317                  pos = strchr(base64, ch);                  pos = strchr(base64, ch);
318                  if (pos == 0)           /* A non-base64 character. */                  if (pos == 0)           /* A non-base64 character. */
319                          return (-1);                          return (-1);
320    
321                  switch (state) {                  switch (state) {
322                  case 0:                  case 0:
323                          if (target) {                          if (target) {
324                                  if (tarindex >= targsize)                                  if (tarindex >= targsize)
325                                          return (-1);                                          return (-1);
326                                  target[tarindex] = (pos - base64) << 2;                                  target[tarindex] = (pos - base64) << 2;
327                          }                          }
328                          state = 1;                          state = 1;
329                          break;                          break;
330                  case 1:                  case 1:
331                          if (target) {                          if (target) {
332                                  if (tarindex + 1 >= targsize)                                  if (tarindex + 1 >= targsize)
333                                          return (-1);                                          return (-1);
334                                  target[tarindex]   |=  (pos - base64) >> 4;                                  target[tarindex]   |=  (pos - base64) >> 4;
335                                  target[tarindex+1]  = ((pos - base64) & 0x0f) << 4 ;                                  target[tarindex+1]  = ((pos - base64) & 0x0f) << 4 ;
336                          }                          }
337                          tarindex++;                          tarindex++;
338                          state = 2;                          state = 2;
339                          break;                          break;
340                  case 2:                  case 2:
341                          if (target) {                          if (target) {
342                                  if (tarindex + 1 >= targsize)                                  if (tarindex + 1 >= targsize)
343                                          return (-1);                                          return (-1);
344                                  target[tarindex]   |=  (pos - base64) >> 2;                                  target[tarindex]   |=  (pos - base64) >> 2;
345                                  target[tarindex+1]  = ((pos - base64) & 0x03) << 6;                                  target[tarindex+1]  = ((pos - base64) & 0x03) << 6;
346                          }                          }
347                          tarindex++;                          tarindex++;
348                          state = 3;                          state = 3;
349                          break;                          break;
350                  case 3:                  case 3:
351                          if (target) {                          if (target) {
352                                  if (tarindex >= targsize)                                  if (tarindex >= targsize)
353                                          return (-1);                                          return (-1);
354                                  target[tarindex] |= (pos - base64);                                  target[tarindex] |= (pos - base64);
355                          }                          }
356                          tarindex++;                          tarindex++;
357                          state = 0;                          state = 0;
358                          break;                          break;
359                  }                  }
360          }          }
361    
362          /*          /*
363           * We are done decoding Base-64 chars.  Let's see if we ended           * We are done decoding Base-64 chars.  Let's see if we ended
364           * on a byte boundary, and/or with erroneous trailing characters.           * on a byte boundary, and/or with erroneous trailing characters.
365           */           */
366    
367          if (ch == pad) {                /* We got a pad char. */          if (ch == pad) {                /* We got a pad char. */
368                  ch = *src++;            /* Skip it, get next. */                  ch = *src++;            /* Skip it, get next. */
369                  switch (state) {                  switch (state) {
370                  case 0:         /* Invalid = in first position */                  case 0:         /* Invalid = in first position */
371                  case 1:         /* Invalid = in second position */                  case 1:         /* Invalid = in second position */
372                          return (-1);                          return (-1);
373    
374                  case 2:         /* Valid, means one byte of info */                  case 2:         /* Valid, means one byte of info */
375                          /* Skip any number of spaces. */                          /* Skip any number of spaces. */
376                          for (; ch != '\0'; ch = *src++)                          for (; ch != '\0'; ch = *src++)
377                                  if (!isspace(ch))                                  if (!isspace(ch))
378                                          break;                                          break;
379                          /* Make sure there is another trailing = sign. */                          /* Make sure there is another trailing = sign. */
380                          if (ch != pad)                          if (ch != pad)
381                                  return (-1);                                  return (-1);
382                          ch = *src++;            /* Skip the = */                          ch = *src++;            /* Skip the = */
383                          /* Fall through to "single trailing =" case. */                          /* Fall through to "single trailing =" case. */
384                          /* FALLTHROUGH */                          /* FALLTHROUGH */
385    
386                  case 3:         /* Valid, means two bytes of info */                  case 3:         /* Valid, means two bytes of info */
387                          /*                          /*
388                           * We know this char is an =.  Is there anything but                           * We know this char is an =.  Is there anything but
389                           * whitespace after it?                           * whitespace after it?
390                           */                           */
391                          for (; ch != '\0'; ch = *src++)                          for (; ch != '\0'; ch = *src++)
392                                  if (!isspace(ch))                                  if (!isspace(ch))
393                                          return (-1);                                          return (-1);
394    
395                          /*                          /*
396                           * Now make sure for cases 2 and 3 that the "extra"                           * Now make sure for cases 2 and 3 that the "extra"
397                           * bits that slopped past the last full byte were                           * bits that slopped past the last full byte were
398                           * zeros.  If we don't check them, they become a                           * zeros.  If we don't check them, they become a
399                           * subliminal channel.                           * subliminal channel.
400                           */                           */
401                          if (target && target[tarindex] != 0)                          if (target && target[tarindex] != 0)
402                                  return (-1);                                  return (-1);
403                  }                  }
404          } else {          } else {
405                  /*                  /*
406                   * We ended by seeing the end of the string.  Make sure we                   * We ended by seeing the end of the string.  Make sure we
407                   * have no partial bytes lying around.                   * have no partial bytes lying around.
408                   */                   */
409                  if (state != 0)                  if (state != 0)
410                          return (-1);                          return (-1);
411          }          }
412    
413          return (tarindex);          return (tarindex);
414  }  }
415    
416    
417  // SSH2鍵は BASE64 形式で格納されている  // SSH2鍵は BASE64 形式で格納されている
418  static Key *parse_uudecode(char *data)  static Key *parse_uudecode(char *data)
419  {  {
420          int count;          int count;
421          unsigned char *blob = NULL;          unsigned char *blob = NULL;
422          int len, n;          int len, n;
423          Key *key = NULL;          Key *key = NULL;
424          char ch;          char ch;
425    
426          // BASE64文字列のサイズを得る          // BASE64文字列のサイズを得る
427          count = eat_base64(data);          count = eat_base64(data);
428          len = 2 * count;          len = 2 * count;
429          blob = malloc(len);          blob = malloc(len);
430          if (blob == NULL)          if (blob == NULL)
431                  goto error;                  goto error;
432    
433          // BASE64デコード          // BASE64デコード
434          ch = data[count];          ch = data[count];
435          data[count] = '\0';  // ここは改行コードのはずなので書き潰しても問題ないはず          data[count] = '\0';  // ここは改行コードのはずなので書き潰しても問題ないはず
436          n = uudecode(data, count, blob, len);          n = uudecode(data, count, blob, len);
437          data[count] = ch;          data[count] = ch;
438          if (n < 0) {          if (n < 0) {
439                  goto error;                  goto error;
440          }          }
441    
442          key = key_from_blob(blob, n);          key = key_from_blob(blob, n);
443          if (key == NULL)          if (key == NULL)
444                  goto error;                  goto error;
445    
446  error:  error:
447          if (blob != NULL)          if (blob != NULL)
448                  free(blob);                  free(blob);
449    
450          return (key);          return (key);
451  }  }
452    
453    
454  static char FAR *parse_bignum(char FAR * data)  static char FAR *parse_bignum(char FAR * data)
455  {  {
456          uint32 digits = 0;          uint32 digits = 0;
457          BIGNUM *num = BN_new();          BIGNUM *num = BN_new();
458          BIGNUM *billion = BN_new();          BIGNUM *billion = BN_new();
459          BIGNUM *digits_num = BN_new();          BIGNUM *digits_num = BN_new();
460          BN_CTX *ctx = BN_CTX_new();          BN_CTX *ctx = BN_CTX_new();
461          char FAR *result;          char FAR *result;
462          int ch;          int ch;
463          int leftover_digits = 1;          int leftover_digits = 1;
464    
465          BN_CTX_init(ctx);          BN_CTX_init(ctx);
466          BN_set_word(num, 0);          BN_set_word(num, 0);
467          BN_set_word(billion, 1000000000L);          BN_set_word(billion, 1000000000L);
468    
469          while ((ch = *data) >= '0' && ch <= '9') {          while ((ch = *data) >= '0' && ch <= '9') {
470                  if (leftover_digits == 1000000000L) {                  if (leftover_digits == 1000000000L) {
471                          BN_set_word(digits_num, digits);                          BN_set_word(digits_num, digits);
472                          BN_mul(num, num, billion, ctx);                          BN_mul(num, num, billion, ctx);
473                          BN_add(num, num, digits_num);                          BN_add(num, num, digits_num);
474                          leftover_digits = 1;                          leftover_digits = 1;
475                          digits = 0;                          digits = 0;
476                  }                  }
477    
478                  digits = digits * 10 + ch - '0';                  digits = digits * 10 + ch - '0';
479                  leftover_digits *= 10;                  leftover_digits *= 10;
480                  data++;                  data++;
481          }          }
482    
483          BN_set_word(digits_num, digits);          BN_set_word(digits_num, digits);
484          BN_set_word(billion, leftover_digits);          BN_set_word(billion, leftover_digits);
485          BN_mul(num, num, billion, ctx);          BN_mul(num, num, billion, ctx);
486          BN_add(num, num, digits_num);          BN_add(num, num, digits_num);
487    
488          result = (char FAR *) malloc(2 + BN_num_bytes(num));          result = (char FAR *) malloc(2 + BN_num_bytes(num));
489          set_ushort16_MSBfirst(result, BN_num_bits(num));          set_ushort16_MSBfirst(result, BN_num_bits(num));
490          BN_bn2bin(num, result + 2);          BN_bn2bin(num, result + 2);
491    
492          BN_CTX_free(ctx);          BN_CTX_free(ctx);
493          BN_free(digits_num);          BN_free(digits_num);
494          BN_free(num);          BN_free(num);
495          BN_free(billion);          BN_free(billion);
496    
497          return result;          return result;
498  }  }
499    
500  //  //
501  // known_hostsファイルの内容を解析し、指定したホストの公開鍵を探す。  // known_hostsファイルの内容を解析し、指定したホストの公開鍵を探す。
502  //  //
503  static int check_host_key(PTInstVar pvar, char FAR * hostname,  static int check_host_key(PTInstVar pvar, char FAR * hostname,
504                            unsigned short tcpport, char FAR * data)                            unsigned short tcpport, char FAR * data)
505  {  {
506          int index = eat_spaces(data);          int index = eat_spaces(data);
507          int matched = 0;          int matched = 0;
508          int keybits = 0;          int keybits = 0;
509    
510          if (data[index] == '#') {          if (data[index] == '#') {
511                  return index + eat_to_end_of_line(data + index);                  return index + eat_to_end_of_line(data + index);
512          }          }
513    
514          /* if we find an empty line, then it won't have any patterns matching the hostname          /* if we find an empty line, then it won't have any patterns matching the hostname
515             and so we skip it */             and so we skip it */
516          index--;          index--;
517          do {          do {
518                  int negated;                  int negated;
519                  int bracketed;                  int bracketed;
520                  char *end_bracket;                  char *end_bracket;
521                  int host_matched = 0;                  int host_matched = 0;
522                  unsigned short keyfile_port = 22;                  unsigned short keyfile_port = 22;
523    
524                  index++;                  index++;
525                  negated = data[index] == '!';                  negated = data[index] == '!';
526    
527                  if (negated) {                  if (negated) {
528                          index++;                          index++;
529                          bracketed = data[index] == '[';                          bracketed = data[index] == '[';
530                          if (bracketed) {                          if (bracketed) {
531                                  end_bracket = strstr(data + index + 1, "]:");                                  end_bracket = strstr(data + index + 1, "]:");
532                                  if (end_bracket != NULL) {                                  if (end_bracket != NULL) {
533                                          *end_bracket = ' ';                                          *end_bracket = ' ';
534                                          index++;                                          index++;
535                                  }                                  }
536                          }                          }
537                          host_matched = match_pattern(data + index, hostname);                          host_matched = match_pattern(data + index, hostname);
538                          if (bracketed && end_bracket != NULL) {                          if (bracketed && end_bracket != NULL) {
539                                  *end_bracket = ']';                                  *end_bracket = ']';
540                                  keyfile_port = atoi(end_bracket + 2);                                  keyfile_port = atoi(end_bracket + 2);
541                          }                          }
542                          if (host_matched && keyfile_port == tcpport) {                          if (host_matched && keyfile_port == tcpport) {
543                                  return index + eat_to_end_of_line(data + index);                                  return index + eat_to_end_of_line(data + index);
544                          }                          }
545                  } else {                  } else {
546                          bracketed = data[index] == '[';                          bracketed = data[index] == '[';
547                          if (bracketed) {                          if (bracketed) {
548                                  end_bracket = strstr(data + index + 1, "]:");                                  end_bracket = strstr(data + index + 1, "]:");
549                                  if (end_bracket != NULL) {                                  if (end_bracket != NULL) {
550                                          *end_bracket = ' ';                                          *end_bracket = ' ';
551                                          index++;                                          index++;
552                                  }                                  }
553                          }                          }
554                          host_matched = match_pattern(data + index, hostname);                          host_matched = match_pattern(data + index, hostname);
555                          if (bracketed && end_bracket != NULL) {                          if (bracketed && end_bracket != NULL) {
556                                  *end_bracket = ']';                                  *end_bracket = ']';
557                                  keyfile_port = atoi(end_bracket + 2);                                  keyfile_port = atoi(end_bracket + 2);
558                          }                          }
559                          if (host_matched && keyfile_port == tcpport) {                          if (host_matched && keyfile_port == tcpport) {
560                                  matched = 1;                                  matched = 1;
561                          }                          }
562                  }                  }
563    
564                  index += eat_to_end_of_pattern(data + index);                  index += eat_to_end_of_pattern(data + index);
565          } while (data[index] == ',');          } while (data[index] == ',');
566    
567          if (!matched) {          if (!matched) {
568                  return index + eat_to_end_of_line(data + index);                  return index + eat_to_end_of_line(data + index);
569          } else {          } else {
570                  // 鍵の種類によりフォーマットが異なる                  // 鍵の種類によりフォーマットが異なる
571                  // また、最初に一致したエントリを取得することになる。                  // また、最初に一致したエントリを取得することになる。
572                  /*                  /*
573                  [SSH1]                  [SSH1]
574                  192.168.1.2 1024 35 13032....                  192.168.1.2 1024 35 13032....
575    
576                  [SSH2]                  [SSH2]
577                  192.168.1.2 ssh-rsa AAAAB3NzaC1....                  192.168.1.2 ssh-rsa AAAAB3NzaC1....
578                  192.168.1.2 ssh-dss AAAAB3NzaC1....                  192.168.1.2 ssh-dss AAAAB3NzaC1....
579                  192.168.1.2 rsa AAAAB3NzaC1....                  192.168.1.2 rsa AAAAB3NzaC1....
580                  192.168.1.2 dsa AAAAB3NzaC1....                  192.168.1.2 dsa AAAAB3NzaC1....
581                  192.168.1.2 rsa1 AAAAB3NzaC1....                  192.168.1.2 rsa1 AAAAB3NzaC1....
582                   */                   */
583                  int rsa1_key_bits;                  int rsa1_key_bits;
584    
585                  index += eat_spaces(data + index);                  index += eat_spaces(data + index);
586    
587                  rsa1_key_bits = atoi(data + index);                  rsa1_key_bits = atoi(data + index);
588                  if (rsa1_key_bits > 0) { // RSA1である                  if (rsa1_key_bits > 0) { // RSA1である
589                          if (!SSHv1(pvar)) { // SSH2接続であれば無視する                          if (!SSHv1(pvar)) { // SSH2接続であれば無視する
590                                  return index + eat_to_end_of_line(data + index);                                  return index + eat_to_end_of_line(data + index);
591                          }                          }
592    
593                          pvar->hosts_state.hostkey.type = KEY_RSA1;                          pvar->hosts_state.hostkey.type = KEY_RSA1;
594    
595                          pvar->hosts_state.hostkey.bits = rsa1_key_bits;                          pvar->hosts_state.hostkey.bits = rsa1_key_bits;
596                          index += eat_digits(data + index);                          index += eat_digits(data + index);
597                          index += eat_spaces(data + index);                          index += eat_spaces(data + index);
598    
599                          pvar->hosts_state.hostkey.exp = parse_bignum(data + index);                          pvar->hosts_state.hostkey.exp = parse_bignum(data + index);
600                          index += eat_digits(data + index);                          index += eat_digits(data + index);
601                          index += eat_spaces(data + index);                          index += eat_spaces(data + index);
602    
603                          pvar->hosts_state.hostkey.mod = parse_bignum(data + index);                          pvar->hosts_state.hostkey.mod = parse_bignum(data + index);
604    
605                          /*                          /*
606                          if (pvar->hosts_state.key_bits < 0                          if (pvar->hosts_state.key_bits < 0
607                                  || pvar->hosts_state.key_exp == NULL                                  || pvar->hosts_state.key_exp == NULL
608                                  || pvar->hosts_state.key_mod == NULL) {                                  || pvar->hosts_state.key_mod == NULL) {
609                                  pvar->hosts_state.key_bits = 0;                                  pvar->hosts_state.key_bits = 0;
610                                  free(pvar->hosts_state.key_exp);                                  free(pvar->hosts_state.key_exp);
611                                  free(pvar->hosts_state.key_mod);                                  free(pvar->hosts_state.key_mod);
612                          }*/                          }*/
613    
614                  } else {                  } else {
615                          char *cp, *p;                          char *cp, *p;
616                          Key *key;                          Key *key;
617    
618                          if (!SSHv2(pvar)) { // SSH1接続であれば無視する                          if (!SSHv2(pvar)) { // SSH1接続であれば無視する
619                                  return index + eat_to_end_of_line(data + index);                                  return index + eat_to_end_of_line(data + index);
620                          }                          }
621    
622                          cp = data + index;                          cp = data + index;
623                          p = strchr(cp, ' ');                          p = strchr(cp, ' ');
624                          if (p == NULL) {                          if (p == NULL) {
625                                  return index + eat_to_end_of_line(data + index);                                  return index + eat_to_end_of_line(data + index);
626                          }                          }
627                          index += (p - cp);  // setup index                          index += (p - cp);  // setup index
628                          *p = '\0';                          *p = '\0';
629                          pvar->hosts_state.hostkey.type = get_keytype_from_name(cp);                          pvar->hosts_state.hostkey.type = get_keytype_from_name(cp);
630                          *p = ' ';                          *p = ' ';
631    
632                          index += eat_spaces(data + index);  // update index                          index += eat_spaces(data + index);  // update index
633    
634                          // uudecode                          // uudecode
635                          key = parse_uudecode(data + index);                          key = parse_uudecode(data + index);
636                          if (key == NULL) {                          if (key == NULL) {
637                                  return index + eat_to_end_of_line(data + index);                                  return index + eat_to_end_of_line(data + index);
638                          }                          }
639    
640                          // setup                          // setup
641                          pvar->hosts_state.hostkey.type = key->type;                          pvar->hosts_state.hostkey.type = key->type;
642                          pvar->hosts_state.hostkey.dsa = key->dsa;                          pvar->hosts_state.hostkey.dsa = key->dsa;
643                          pvar->hosts_state.hostkey.rsa = key->rsa;                          pvar->hosts_state.hostkey.rsa = key->rsa;
644    
645                          index += eat_base64(data + index);                          index += eat_base64(data + index);
646                          index += eat_spaces(data + index);                          index += eat_spaces(data + index);
647    
648                          // Key構造体自身を解放する (2008.3.2 yutaka)                          // Key構造体自身を解放する (2008.3.2 yutaka)
649                          free(key);                          free(key);
650                  }                  }
651    
652                  return index + eat_to_end_of_line(data + index);                  return index + eat_to_end_of_line(data + index);
653          }          }
654  }  }
655    
656  //  //
657  // known_hostsファイルからホスト名に合致する行を読む  // known_hostsファイルからホスト名に合致する行を読む
658  //  //
659  static int read_host_key(PTInstVar pvar,  static int read_host_key(PTInstVar pvar,
660                           char FAR * hostname, unsigned short tcpport,                           char FAR * hostname, unsigned short tcpport,
661                           int suppress_errors, int return_always)                           int suppress_errors, int return_always)
662  {  {
663          int i;          int i;
664          int while_flg;          int while_flg;
665    
666          for (i = 0; hostname[i] != 0; i++) {          for (i = 0; hostname[i] != 0; i++) {
667                  int ch = hostname[i];                  int ch = hostname[i];
668    
669                  if (!is_pattern_char(ch) || ch == '*' || ch == '?') {                  if (!is_pattern_char(ch) || ch == '*' || ch == '?') {
670                          if (!suppress_errors) {                          if (!suppress_errors) {
671                                  UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_INVALID_ERROR", pvar,
672                                                    "The host name contains an invalid character.\n"                                                    "The host name contains an invalid character.\n"
673                                                    "This session will be terminated.");                                                    "This session will be terminated.");
674                                  notify_fatal_error(pvar, pvar->ts->UIMsg);                                  notify_fatal_error(pvar, pvar->ts->UIMsg);
675                          }                          }
676                          return 0;                          return 0;
677                  }                  }
678          }          }
679    
680          if (i == 0) {          if (i == 0) {
681                  if (!suppress_errors) {                  if (!suppress_errors) {
682                          UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,                          UTIL_get_lang_msg("MSG_HOSTS_HOSTNAME_EMPTY_ERROR", pvar,
683                                            "The host name should not be empty.\n"                                            "The host name should not be empty.\n"
684                                            "This session will be terminated.");                                            "This session will be terminated.");
685                          notify_fatal_error(pvar, pvar->ts->UIMsg);                          notify_fatal_error(pvar, pvar->ts->UIMsg);
686                  }                  }
687                  return 0;                  return 0;
688          }          }
689    
690  #if 0  #if 0
691          pvar->hosts_state.key_bits = 0;          pvar->hosts_state.key_bits = 0;
692          free(pvar->hosts_state.key_exp);          free(pvar->hosts_state.key_exp);
693          pvar->hosts_state.key_exp = NULL;          pvar->hosts_state.key_exp = NULL;
694          free(pvar->hosts_state.key_mod);          free(pvar->hosts_state.key_mod);
695          pvar->hosts_state.key_mod = NULL;          pvar->hosts_state.key_mod = NULL;
696  #else  #else
697          // hostkey type is KEY_UNSPEC.          // hostkey type is KEY_UNSPEC.
698          init_hostkey(&pvar->hosts_state.hostkey);          init_hostkey(&pvar->hosts_state.hostkey);
699  #endif  #endif
700    
701          do {          do {
702                  if (pvar->hosts_state.file_data == NULL                  if (pvar->hosts_state.file_data == NULL
703                   || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {                   || pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] == 0) {
704                          char FAR *filename;                          char FAR *filename;
705                          int keep_going = 1;                          int keep_going = 1;
706    
707                          if (pvar->hosts_state.file_data != NULL) {                          if (pvar->hosts_state.file_data != NULL) {
708                                  end_read_file(pvar, suppress_errors);                                  end_read_file(pvar, suppress_errors);
709                          }                          }
710    
711                          do {                          do {
712                                  filename =                                  filename =
713                                          pvar->hosts_state.file_names[pvar->hosts_state.file_num];                                          pvar->hosts_state.file_names[pvar->hosts_state.file_num];
714    
715                                  if (filename == NULL) {                                  if (filename == NULL) {
716                                          return 1;                                          return 1;
717                                  } else {                                  } else {
718                                          pvar->hosts_state.file_num++;                                          pvar->hosts_state.file_num++;
719    
720                                          if (filename[0] != 0) {                                          if (filename[0] != 0) {
721                                                  if (begin_read_file(pvar, filename, suppress_errors)) {                                                  if (begin_read_file(pvar, filename, suppress_errors)) {
722                                                          pvar->hosts_state.file_data_index = 0;                                                          pvar->hosts_state.file_data_index = 0;
723                                                          keep_going = 0;                                                          keep_going = 0;
724                                                  }                                                  }
725                                          }                                          }
726                                  }                                  }
727                          } while (keep_going);                          } while (keep_going);
728                  }                  }
729    
730                  pvar->hosts_state.file_data_index +=                  pvar->hosts_state.file_data_index +=
731                          check_host_key(pvar, hostname, tcpport,                          check_host_key(pvar, hostname, tcpport,
732                                         pvar->hosts_state.file_data +                                         pvar->hosts_state.file_data +
733                                         pvar->hosts_state.file_data_index);                                         pvar->hosts_state.file_data_index);
734    
735                  if (!return_always) {                  if (!return_always) {
736                          // 有効なキーが見つかるまで                          // 有効なキーが見つかるまで
737                          while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);                          while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC);
738                  }                  }
739                  else {                  else {
740                          while_flg = 0;                          while_flg = 0;
741                  }                  }
742          } while (while_flg);          } while (while_flg);
743    
744          return 1;          return 1;
745  }  }
746    
747  static void finish_read_host_files(PTInstVar pvar, int suppress_errors)  static void finish_read_host_files(PTInstVar pvar, int suppress_errors)
748  {  {
749          if (pvar->hosts_state.file_data != NULL) {          if (pvar->hosts_state.file_data != NULL) {
750                  end_read_file(pvar, suppress_errors);                  end_read_file(pvar, suppress_errors);
751          }          }
752  }  }
753    
754  // サーバへ接続する前に、known_hostsファイルからホスト公開鍵を先読みしておく。  // サーバへ接続する前に、known_hostsファイルからホスト公開鍵を先読みしておく。
755  void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport)  void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport)
756  {  {
757          if (!begin_read_host_files(pvar, 1)) {          if (!begin_read_host_files(pvar, 1)) {
758                  return;                  return;
759          }          }
760    
761          if (!read_host_key(pvar, hostname, tcpport, 1, 0)) {          if (!read_host_key(pvar, hostname, tcpport, 1, 0)) {
762                  return;                  return;
763          }          }
764    
765          free(pvar->hosts_state.prefetched_hostname);          free(pvar->hosts_state.prefetched_hostname);
766          pvar->hosts_state.prefetched_hostname = _strdup(hostname);          pvar->hosts_state.prefetched_hostname = _strdup(hostname);
767    
768          finish_read_host_files(pvar, 1);          finish_read_host_files(pvar, 1);
769  }  }
770    
771  static BOOL equal_mp_ints(unsigned char FAR * num1,  static BOOL equal_mp_ints(unsigned char FAR * num1,
772                            unsigned char FAR * num2)                            unsigned char FAR * num2)
773  {  {
774          if (num1 == NULL || num2 == NULL) {          if (num1 == NULL || num2 == NULL) {
775                  return FALSE;                  return FALSE;
776          } else {          } else {
777                  uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;                  uint32 bytes = (get_ushort16_MSBfirst(num1) + 7) / 8;
778    
779                  if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {                  if (bytes != (get_ushort16_MSBfirst(num2) + 7) / 8) {
780                          return FALSE;           /* different byte lengths */                          return FALSE;           /* different byte lengths */
781                  } else {                  } else {
782                          return memcmp(num1 + 2, num2 + 2, bytes) == 0;                          return memcmp(num1 + 2, num2 + 2, bytes) == 0;
783                  }                  }
784          }          }
785  }  }
786    
787  // 公開鍵が等しいかを検証する  // 公開鍵が等しいかを検証する
788  static BOOL match_key(PTInstVar pvar, Key *key)  static BOOL match_key(PTInstVar pvar, Key *key)
789  {  {
790          int bits;          int bits;
791          unsigned char FAR * exp;          unsigned char FAR * exp;
792          unsigned char FAR * mod;          unsigned char FAR * mod;
793    
794          if (key->type == KEY_RSA1) {  // SSH1 host public key          if (key->type == KEY_RSA1) {  // SSH1 host public key
795                  bits = key->bits;                  bits = key->bits;
796                  exp = key->exp;                  exp = key->exp;
797                  mod = key->mod;                  mod = key->mod;
798    
799                  /* just check for equal exponent and modulus */                  /* just check for equal exponent and modulus */
800                  return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)                  return equal_mp_ints(exp, pvar->hosts_state.hostkey.exp)
801                      && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);                      && equal_mp_ints(mod, pvar->hosts_state.hostkey.mod);
802                  /*                  /*
803                  return equal_mp_ints(exp, pvar->hosts_state.key_exp)                  return equal_mp_ints(exp, pvar->hosts_state.key_exp)
804                          && equal_mp_ints(mod, pvar->hosts_state.key_mod);                          && equal_mp_ints(mod, pvar->hosts_state.key_mod);
805                          */                          */
806    
807          } else if (key->type == KEY_RSA) {  // SSH2 RSA host public key          } else if (key->type == KEY_RSA) {  // SSH2 RSA host public key
808    
809                  return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&                  return key->rsa != NULL && pvar->hosts_state.hostkey.rsa != NULL &&
810                         BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&                         BN_cmp(key->rsa->e, pvar->hosts_state.hostkey.rsa->e) == 0 &&
811                         BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;                         BN_cmp(key->rsa->n, pvar->hosts_state.hostkey.rsa->n) == 0;
812    
813          } else { // // SSH2 DSA host public key          } else { // // SSH2 DSA host public key
814    
815                  return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&                  return key->dsa != NULL && pvar->hosts_state.hostkey.dsa &&
816                         BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&                         BN_cmp(key->dsa->p, pvar->hosts_state.hostkey.dsa->p) == 0 &&
817                         BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&                         BN_cmp(key->dsa->q, pvar->hosts_state.hostkey.dsa->q) == 0 &&
818                         BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&                         BN_cmp(key->dsa->g, pvar->hosts_state.hostkey.dsa->g) == 0 &&
819                         BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;                         BN_cmp(key->dsa->pub_key, pvar->hosts_state.hostkey.dsa->pub_key) == 0;
820    
821          }          }
822    
823  }  }
824    
825  static void init_hosts_dlg(PTInstVar pvar, HWND dlg)  static void init_hosts_dlg(PTInstVar pvar, HWND dlg)
826  {  {
827          char buf[1024];          char buf[1024];
828          char buf2[2048];          char buf2[2048];
829          int i, j;          int i, j;
830          int ch;          int ch;
831          char *fp = NULL;          char *fp = NULL;
832    
833          // static textの # 部分をホスト名に置換する          // static textの # 部分をホスト名に置換する
834          GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));          GetDlgItemText(dlg, IDC_HOSTWARNING, buf, sizeof(buf));
835          for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {          for (i = 0; (ch = buf[i]) != 0 && ch != '#'; i++) {
836                  buf2[i] = ch;                  buf2[i] = ch;
837          }          }
838          strncpy_s(buf2 + i, sizeof(buf2) - i,          strncpy_s(buf2 + i, sizeof(buf2) - i,
839                    pvar->hosts_state.prefetched_hostname, _TRUNCATE);                    pvar->hosts_state.prefetched_hostname, _TRUNCATE);
840          j = i + strlen(buf2 + i);          j = i + strlen(buf2 + i);
841          for (; buf[i] == '#'; i++) {          for (; buf[i] == '#'; i++) {
842          }          }
843          strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);          strncpy_s(buf2 + j, sizeof(buf2) - j, buf + i, _TRUNCATE);
844    
845          SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);          SetDlgItemText(dlg, IDC_HOSTWARNING, buf2);
846    
847          // fingerprintを設定する          // fingerprintを設定する
848          fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX);          fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX);
849          SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);          SendMessage(GetDlgItem(dlg, IDC_FINGER_PRINT), WM_SETTEXT, 0, (LPARAM)fp);
850          free(fp);          free(fp);
851    
852          // ビジュアル化fingerprintを表示する          // ビジュアル化fingerprintを表示する
853          fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART);          fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART);
854          SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);          SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETTEXT, 0, (LPARAM)fp);
855          SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);          SendMessage(GetDlgItem(dlg, IDC_FP_RANDOMART), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE);
856          free(fp);          free(fp);
857  }  }
858    
859  static int print_mp_int(char FAR * buf, unsigned char FAR * mp)  static int print_mp_int(char FAR * buf, unsigned char FAR * mp)
860  {  {
861          int i = 0, j, k;          int i = 0, j, k;
862          BIGNUM *num = BN_new();          BIGNUM *num = BN_new();
863          int ch;          int ch;
864    
865          BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);          BN_bin2bn(mp + 2, (get_ushort16_MSBfirst(mp) + 7) / 8, num);
866    
867          do {          do {
868                  buf[i] = (char) ((BN_div_word(num, 10)) + '0');                  buf[i] = (char) ((BN_div_word(num, 10)) + '0');
869                  i++;                  i++;
870          } while (!BN_is_zero(num));          } while (!BN_is_zero(num));
871    
872          /* we need to reverse the digits */          /* we need to reverse the digits */
873          for (j = 0, k = i - 1; j < k; j++, k--) {          for (j = 0, k = i - 1; j < k; j++, k--) {
874                  ch = buf[j];                  ch = buf[j];
875                  buf[j] = buf[k];                  buf[j] = buf[k];
876                  buf[k] = ch;                  buf[k] = ch;
877          }          }
878    
879          buf[i] = 0;          buf[i] = 0;
880          return i;          return i;
881  }  }
882    
883  //  //
884  // known_hosts ファイルへ保存するエントリを作成する。  // known_hosts ファイルへ保存するエントリを作成する。
885  //  //
886  static char FAR *format_host_key(PTInstVar pvar)  static char FAR *format_host_key(PTInstVar pvar)
887  {  {
888          int host_len = strlen(pvar->hosts_state.prefetched_hostname);          int host_len = strlen(pvar->hosts_state.prefetched_hostname);
889          char *result = NULL;          char *result = NULL;
890          int index;          int index;
891          enum hostkey_type type = pvar->hosts_state.hostkey.type;          enum hostkey_type type = pvar->hosts_state.hostkey.type;
892    
893          if (type == KEY_RSA1) {          if (type == KEY_RSA1) {
894                  int result_len = host_len + 50 + 8 +                  int result_len = host_len + 50 + 8 +
895                                   get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +                                   get_ushort16_MSBfirst(pvar->hosts_state.hostkey.exp) / 3 +
896                                   get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;                                   get_ushort16_MSBfirst(pvar->hosts_state.hostkey.mod) / 3;
897                  result = (char FAR *) malloc(result_len);                  result = (char FAR *) malloc(result_len);
898    
899                  if (pvar->ssh_state.tcpport == 22) {                  if (pvar->ssh_state.tcpport == 22) {
900                          strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);                          strncpy_s(result, result_len, pvar->hosts_state.prefetched_hostname, _TRUNCATE);
901                          index = host_len;                          index = host_len;
902                  }                  }
903                  else {                  else {
904                          _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",                          _snprintf_s(result, result_len, _TRUNCATE, "[%s]:%d",
905                                      pvar->hosts_state.prefetched_hostname,                                      pvar->hosts_state.prefetched_hostname,
906                                      pvar->ssh_state.tcpport);                                      pvar->ssh_state.tcpport);
907                          index = strlen(result);                          index = strlen(result);
908                  }                  }
909    
910                  _snprintf_s(result + index, result_len - host_len, _TRUNCATE,                  _snprintf_s(result + index, result_len - host_len, _TRUNCATE,
911                              " %d ", pvar->hosts_state.hostkey.bits);                              " %d ", pvar->hosts_state.hostkey.bits);
912                  index += strlen(result + index);                  index += strlen(result + index);
913                  index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);                  index += print_mp_int(result + index, pvar->hosts_state.hostkey.exp);
914                  result[index] = ' ';                  result[index] = ' ';
915                  index++;                  index++;
916                  index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);                  index += print_mp_int(result + index, pvar->hosts_state.hostkey.mod);
917                  strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);                  strncpy_s(result + index, result_len - index, " \r\n", _TRUNCATE);
918    
919          } else if (type == KEY_RSA || type == KEY_DSA) {          } else if (type == KEY_RSA || type == KEY_DSA) {
920                  Key *key = &pvar->hosts_state.hostkey;                  Key *key = &pvar->hosts_state.hostkey;
921                  char *blob = NULL;                  char *blob = NULL;
922                  int blen, uulen, msize;                  int blen, uulen, msize;
923                  char *uu = NULL;                  char *uu = NULL;
924                  int n;                  int n;
925    
926                  key_to_blob(key, &blob, &blen);                  key_to_blob(key, &blob, &blen);
927                  uulen = 2 * blen;                  uulen = 2 * blen;
928                  uu = malloc(uulen);                  uu = malloc(uulen);
929                  if (uu == NULL) {                  if (uu == NULL) {
930                          goto error;                          goto error;
931                  }                  }
932                  n = uuencode(blob, blen, uu, uulen);                  n = uuencode(blob, blen, uu, uulen);
933                  if (n > 0) {                  if (n > 0) {
934                          msize = host_len + 50 + uulen;                          msize = host_len + 50 + uulen;
935                          result = malloc(msize);                          result = malloc(msize);
936                          if (result == NULL) {                          if (result == NULL) {
937                                  goto error;                                  goto error;
938                          }                          }
939    
940                          // setup                          // setup
941                          if (pvar->ssh_state.tcpport == 22) {                          if (pvar->ssh_state.tcpport == 22) {
942                                  _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",                                  _snprintf_s(result, msize, _TRUNCATE, "%s %s %s\r\n",
943                                              pvar->hosts_state.prefetched_hostname,                                              pvar->hosts_state.prefetched_hostname,
944                                              get_sshname_from_key(key),                                              get_sshname_from_key(key),
945                                              uu);                                              uu);
946                          } else {                          } else {
947                                  _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",                                  _snprintf_s(result, msize, _TRUNCATE, "[%s]:%d %s %s\r\n",
948                                              pvar->hosts_state.prefetched_hostname,                                              pvar->hosts_state.prefetched_hostname,
949                                              pvar->ssh_state.tcpport,                                              pvar->ssh_state.tcpport,
950                                              get_sshname_from_key(key),                                              get_sshname_from_key(key),
951                                              uu);                                              uu);
952                          }                          }
953                  }                  }
954  error:  error:
955                  if (blob != NULL)                  if (blob != NULL)
956                          free(blob);                          free(blob);
957                  if (uu != NULL)                  if (uu != NULL)
958                          free(uu);                          free(uu);
959    
960          } else {          } else {
961                  return NULL;                  return NULL;
962    
963          }          }
964    
965          return result;          return result;
966  }  }
967    
968  static void add_host_key(PTInstVar pvar)  static void add_host_key(PTInstVar pvar)
969  {  {
970          char FAR *name = NULL;          char FAR *name = NULL;
971    
972          if ( pvar->hosts_state.file_names != NULL)          if ( pvar->hosts_state.file_names != NULL)
973                  name = pvar->hosts_state.file_names[0];                  name = pvar->hosts_state.file_names[0];
974    
975          if (name == NULL || name[0] == 0) {          if (name == NULL || name[0] == 0) {
976                  UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,                  UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
977                                    "The host and its key cannot be added, because no known-hosts file has been specified.\n"                                    "The host and its key cannot be added, because no known-hosts file has been specified.\n"
978                                    "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");                                    "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
979                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
980          } else {          } else {
981                  char FAR *keydata = format_host_key(pvar);                  char FAR *keydata = format_host_key(pvar);
982                  int length = strlen(keydata);                  int length = strlen(keydata);
983                  int fd;                  int fd;
984                  int amount_written;                  int amount_written;
985                  int close_result;                  int close_result;
986                  char buf[FILENAME_MAX];                  char buf[FILENAME_MAX];
987    
988                  get_teraterm_dir_relative_name(buf, sizeof(buf), name);                  get_teraterm_dir_relative_name(buf, sizeof(buf), name);
989                  fd = _open(buf,                  fd = _open(buf,
990                            _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,                            _O_APPEND | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY,
991                            _S_IREAD | _S_IWRITE);                            _S_IREAD | _S_IWRITE);
992                  if (fd == -1) {                  if (fd == -1) {
993                          if (errno == EACCES) {                          if (errno == EACCES) {
994                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
995                                                    "An error occurred while trying to write the host key.\n"                                                    "An error occurred while trying to write the host key.\n"
996                                                    "You do not have permission to write to the known-hosts file.");                                                    "You do not have permission to write to the known-hosts file.");
997                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
998                          } else {                          } else {
999                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1000                                                    "An error occurred while trying to write the host key.\n"                                                    "An error occurred while trying to write the host key.\n"
1001                                                    "The host key could not be written.");                                                    "The host key could not be written.");
1002                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1003                          }                          }
1004                          return;                          return;
1005                  }                  }
1006    
1007                  amount_written = _write(fd, keydata, length);                  amount_written = _write(fd, keydata, length);
1008                  free(keydata);                  free(keydata);
1009                  close_result = _close(fd);                  close_result = _close(fd);
1010    
1011                  if (amount_written != length || close_result == -1) {                  if (amount_written != length || close_result == -1) {
1012                          UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,                          UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1013                                            "An error occurred while trying to write the host key.\n"                                            "An error occurred while trying to write the host key.\n"
1014                                            "The host key could not be written.");                                            "The host key could not be written.");
1015                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1016                  }                  }
1017          }          }
1018  }  }
1019    
1020  static char FAR *copy_mp_int(char FAR * num)  static char FAR *copy_mp_int(char FAR * num)
1021  {  {
1022          int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;          int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2;
1023          char FAR *result = (char FAR *) malloc(len);          char FAR *result = (char FAR *) malloc(len);
1024    
1025          if (result != NULL) {          if (result != NULL) {
1026                  memcpy(result, num, len);                  memcpy(result, num, len);
1027          }          }
1028    
1029          return result;          return result;
1030  }  }
1031    
1032  //  //
1033  // 同じホストで内容の異なるキーを削除する  // 同じホストで内容の異なるキーを削除する
1034  // add_host_key のあとに呼ぶこと  // add_host_key のあとに呼ぶこと
1035  //  //
1036  static void delete_different_key(PTInstVar pvar)  static void delete_different_key(PTInstVar pvar)
1037  {  {
1038          char FAR *name = pvar->hosts_state.file_names[0];          char FAR *name = pvar->hosts_state.file_names[0];
1039    
1040          if (name == NULL || name[0] == 0) {          if (name == NULL || name[0] == 0) {
1041                  UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,                  UTIL_get_lang_msg("MSG_HOSTS_FILE_UNSPECIFY_ERROR", pvar,
1042                                    "The host and its key cannot be added, because no known-hosts file has been specified.\n"                                    "The host and its key cannot be added, because no known-hosts file has been specified.\n"
1043                                    "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");                                    "Restart Tera Term and specify a read/write known-hosts file in the TTSSH Setup dialog box.");
1044                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1045          }          }
1046          else {          else {
1047                  Key key; // 接続中のホストのキー                  Key key; // 接続中のホストのキー
1048                  int length;                  int length;
1049                  char filename[MAX_PATH];                  char filename[MAX_PATH];
1050                  char tmp[L_tmpnam];                  char tmp[L_tmpnam];
1051                  int fd;                  int fd;
1052                  int amount_written = 0;                  int amount_written = 0;
1053                  int close_result;                  int close_result;
1054                  int data_index = 0;                  int data_index = 0;
1055                  char buf[FILENAME_MAX];                  char buf[FILENAME_MAX];
1056    
1057                  // 書き込み一時ファイルを開く                  // 書き込み一時ファイルを開く
1058                  _getcwd(filename, sizeof(filename));                  _getcwd(filename, sizeof(filename));
1059                  tmpnam_s(tmp,sizeof(tmp));                  tmpnam_s(tmp,sizeof(tmp));
1060                  strcat_s(filename, sizeof(filename), tmp);                  strcat_s(filename, sizeof(filename), tmp);
1061                  fd = _open(filename,                  fd = _open(filename,
1062                            _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,                            _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | _O_TRUNC,
1063                            _S_IREAD | _S_IWRITE);                            _S_IREAD | _S_IWRITE);
1064    
1065                  if (fd == -1) {                  if (fd == -1) {
1066                          if (errno == EACCES) {                          if (errno == EACCES) {
1067                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_EACCES_ERROR", pvar,
1068                                                    "An error occurred while trying to write the host key.\n"                                                    "An error occurred while trying to write the host key.\n"
1069                                                    "You do not have permission to write to the known-hosts file.");                                                    "You do not have permission to write to the known-hosts file.");
1070                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1071                          } else {                          } else {
1072                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1073                                                    "An error occurred while trying to write the host key.\n"                                                    "An error occurred while trying to write the host key.\n"
1074                                                    "The host key could not be written.");                                                    "The host key could not be written.");
1075                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);                                  notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1076                          }                          }
1077                          return;                          return;
1078                  }                  }
1079    
1080                  // 接続中のサーバのキーを読み込む                  // 接続中のサーバのキーを読み込む
1081                  if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1                  if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1
1082                          key.type = KEY_RSA1;                          key.type = KEY_RSA1;
1083                          key.bits = pvar->hosts_state.hostkey.bits;                          key.bits = pvar->hosts_state.hostkey.bits;
1084                          key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);                          key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp);
1085                          key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);                          key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod);
1086                  } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA                  } else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA
1087                          key.type = KEY_RSA;                          key.type = KEY_RSA;
1088                          key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);                          key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa);
1089                  } else { // SSH2 DSA                  } else { // SSH2 DSA
1090                          key.type = KEY_DSA;                          key.type = KEY_DSA;
1091                          key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);                          key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa);
1092                  }                  }
1093    
1094                  // ファイルから読み込む                  // ファイルから読み込む
1095                  begin_read_host_files(pvar, 0);                  begin_read_host_files(pvar, 0);
1096                  do {                  do {
1097                          int host_index = 0;                          int host_index = 0;
1098                          int matched = 0;                          int matched = 0;
1099                          int keybits = 0;                          int keybits = 0;
1100                          char FAR *data;                          char FAR *data;
1101                          int do_write = 0;                          int do_write = 0;
1102                          length = amount_written = 0;                          length = amount_written = 0;
1103    
1104                          if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {                          if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) {
1105                                  break;                                  break;
1106                          }                          }
1107    
1108                          if (data_index == pvar->hosts_state.file_data_index) {                          if (data_index == pvar->hosts_state.file_data_index) {
1109                                  // index が進まない == 最後まで読んだ                                  // index が進まない == 最後まで読んだ
1110                                  break;                                  break;
1111                          }                          }
1112    
1113                          data = pvar->hosts_state.file_data + data_index;                          data = pvar->hosts_state.file_data + data_index;
1114                          host_index = eat_spaces(data);                          host_index = eat_spaces(data);
1115    
1116                          if (data[host_index] == '#') {                          if (data[host_index] == '#') {
1117                                  do_write = 1;                                  do_write = 1;
1118                          }                          }
1119                          else {                          else {
1120                                  // ホストの照合                                  // ホストの照合
1121                                  host_index--;                                  host_index--;
1122                                  do {                                  do {
1123                                          int negated;                                          int negated;
1124                                          int bracketed;                                          int bracketed;
1125                                          char *end_bracket;                                          char *end_bracket;
1126                                          int host_matched = 0;                                          int host_matched = 0;
1127                                          unsigned short keyfile_port = 22;                                          unsigned short keyfile_port = 22;
1128    
1129                                          host_index++;                                          host_index++;
1130                                          negated = data[host_index] == '!';                                          negated = data[host_index] == '!';
1131    
1132                                          if (negated) {                                          if (negated) {
1133                                                  host_index++;                                                  host_index++;
1134                                                  bracketed = data[host_index] == '[';                                                  bracketed = data[host_index] == '[';
1135                                                  if (bracketed) {                                                  if (bracketed) {
1136                                                          end_bracket = strstr(data + host_index + 1, "]:");                                                          end_bracket = strstr(data + host_index + 1, "]:");
1137                                                          if (end_bracket != NULL) {                                                          if (end_bracket != NULL) {
1138                                                                  *end_bracket = ' ';                                                                  *end_bracket = ' ';
1139                                                                  host_index++;                                                                  host_index++;
1140                                                          }                                                          }
1141                                                  }                                                  }
1142                                                  host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);                                                  host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1143                                                  if (bracketed && end_bracket != NULL) {                                                  if (bracketed && end_bracket != NULL) {
1144                                                          *end_bracket = ']';                                                          *end_bracket = ']';
1145                                                          keyfile_port = atoi(end_bracket + 2);                                                          keyfile_port = atoi(end_bracket + 2);
1146                                                  }                                                  }
1147                                                  if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {                                                  if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1148                                                          matched = 0;                                                          matched = 0;
1149                                                          // 接続バージョンチェックのために host_index を進めてから抜ける                                                          // 接続バージョンチェックのために host_index を進めてから抜ける
1150                                                          host_index--;                                                          host_index--;
1151                                                          do {                                                          do {
1152                                                                  host_index++;                                                                  host_index++;
1153                                                                  host_index += eat_to_end_of_pattern(data + host_index);                                                                  host_index += eat_to_end_of_pattern(data + host_index);
1154                                                          } while (data[host_index] == ',');                                                          } while (data[host_index] == ',');
1155                                                          break;                                                          break;
1156                                                  }                                                  }
1157                                          }                                          }
1158                                          else {                                          else {
1159                                                  bracketed = data[host_index] == '[';                                                  bracketed = data[host_index] == '[';
1160                                                  if (bracketed) {                                                  if (bracketed) {
1161                                                          end_bracket = strstr(data + host_index + 1, "]:");                                                          end_bracket = strstr(data + host_index + 1, "]:");
1162                                                          if (end_bracket != NULL) {                                                          if (end_bracket != NULL) {
1163                                                                  *end_bracket = ' ';                                                                  *end_bracket = ' ';
1164                                                                  host_index++;                                                                  host_index++;
1165                                                          }                                                          }
1166                                                  }                                                  }
1167                                                  host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);                                                  host_matched = match_pattern(data + host_index, pvar->ssh_state.hostname);
1168                                                  if (bracketed && end_bracket != NULL) {                                                  if (bracketed && end_bracket != NULL) {
1169                                                          *end_bracket = ']';                                                          *end_bracket = ']';
1170                                                          keyfile_port = atoi(end_bracket + 2);                                                          keyfile_port = atoi(end_bracket + 2);
1171                                                  }                                                  }
1172                                                  if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {                                                  if (host_matched && keyfile_port == pvar->ssh_state.tcpport) {
1173                                                          matched = 1;                                                          matched = 1;
1174                                                  }                                                  }
1175                                          }                                          }
1176                                          host_index += eat_to_end_of_pattern(data + host_index);                                          host_index += eat_to_end_of_pattern(data + host_index);
1177                                  } while (data[host_index] == ',');                                  } while (data[host_index] == ',');
1178    
1179                                  // ホストが等しくて合致するキーが見つかる                                  // ホストが等しくて合致するキーが見つかる
1180                                  if (match_key(pvar, &key)) {                                  if (match_key(pvar, &key)) {
1181                                          do_write = 1;                                          do_write = 1;
1182                                  }                                  }
1183                                  // ホストが等しくない                                  // ホストが等しくない
1184                                  else if (!matched) {                                  else if (!matched) {
1185                                          do_write = 1;                                          do_write = 1;
1186                                  }                                  }
1187                                  // ホストが等しい and 接続のバージョンが違う                                  // ホストが等しい and 接続のバージョンが違う
1188                                  else {                                  else {
1189                                          int rsa1_key_bits=0;                                          int rsa1_key_bits=0;
1190                                          rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));                                          rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index));
1191                                                                                    
1192                                          if (rsa1_key_bits > 0) { // ファイルのキーは ssh1                                          if (rsa1_key_bits > 0) { // ファイルのキーは ssh1
1193                                                  if (!SSHv1(pvar)) {                                                  if (!SSHv1(pvar)) {
1194                                                          do_write = 1;                                                          do_write = 1;
1195                                                  }                                                  }
1196                                          }                                          }
1197                                          else { // ファイルのキーは ssh2                                          else { // ファイルのキーは ssh2
1198                                                  if (!SSHv2(pvar)) {                                                  if (!SSHv2(pvar)) {
1199                                                          do_write = 1;                                                          do_write = 1;
1200                                                  }                                                  }
1201                                          }                                          }
1202                                  }                                  }
1203                          }                          }
1204    
1205                          // 書き込み処理                          // 書き込み処理
1206                          if (do_write) {                          if (do_write) {
1207                                  length = pvar->hosts_state.file_data_index - data_index;                                  length = pvar->hosts_state.file_data_index - data_index;
1208                                  amount_written =                                  amount_written =
1209                                          _write(fd, pvar->hosts_state.file_data + data_index,                                          _write(fd, pvar->hosts_state.file_data + data_index,
1210                                                 length);                                                 length);
1211    
1212                                  if (amount_written != length) {                                  if (amount_written != length) {
1213                                          goto error1;                                          goto error1;
1214                                  }                                  }
1215                          }                          }
1216                          data_index = pvar->hosts_state.file_data_index;                          data_index = pvar->hosts_state.file_data_index;
1217                  } while (1); // 最後まで読む                  } while (1); // 最後まで読む
1218    
1219  error1:  error1:
1220                  close_result = _close(fd);                  close_result = _close(fd);
1221                  if (amount_written != length || close_result == -1) {                  if (amount_written != length || close_result == -1) {
1222                          UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,                          UTIL_get_lang_msg("MSG_HOSTS_WRITE_ERROR", pvar,
1223                                            "An error occurred while trying to write the host key.\n"                                            "An error occurred while trying to write the host key.\n"
1224                                            "The host key could not be written.");                                            "The host key could not be written.");
1225                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);                          notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1226                          goto error2;                          goto error2;
1227                  }                  }
1228    
1229                  // 書き込み一時ファイルからリネーム                  // 書き込み一時ファイルからリネーム
1230                  get_teraterm_dir_relative_name(buf, sizeof(buf), name);                  get_teraterm_dir_relative_name(buf, sizeof(buf), name);
1231                  _unlink(buf);                  _unlink(buf);
1232                  rename(filename, buf);                  rename(filename, buf);
1233    
1234  error2:  error2:
1235                  _unlink(filename);                  _unlink(filename);
1236    
1237                  finish_read_host_files(pvar, 0);                  finish_read_host_files(pvar, 0);
1238          }          }
1239  }  }
1240    
1241  //  //
1242  // Unknown hostのホスト公開鍵を known_hosts ファイルへ保存するかどうかを  // Unknown hostのホスト公開鍵を known_hosts ファイルへ保存するかどうかを
1243  // ユーザに確認させる。  // ユーザに確認させる。
1244  // TODO: finger printの表示も行う。  // TODO: finger printの表示も行う。
1245  // (2006.3.25 yutaka)  // (2006.3.25 yutaka)
1246  //  //
1247  static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,  static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1248                                          LPARAM lParam)                                          LPARAM lParam)
1249  {  {
1250          PTInstVar pvar;          PTInstVar pvar;
1251          LOGFONT logfont;          LOGFONT logfont;
1252          HFONT font;          HFONT font;
1253          char uimsg[MAX_UIMSG];          char uimsg[MAX_UIMSG];
1254    
1255          switch (msg) {          switch (msg) {
1256          case WM_INITDIALOG:          case WM_INITDIALOG:
1257                  pvar = (PTInstVar) lParam;                  pvar = (PTInstVar) lParam;
1258                  pvar->hosts_state.hosts_dialog = dlg;                  pvar->hosts_state.hosts_dialog = dlg;
1259                  SetWindowLong(dlg, DWL_USER, lParam);                  SetWindowLong(dlg, DWL_USER, lParam);
1260    
1261                  // 追加・置き換えとも init_hosts_dlg を呼んでいるので、その前にセットする必要がある                  // 追加・置き換えとも init_hosts_dlg を呼んでいるので、その前にセットする必要がある
1262                  GetWindowText(dlg, uimsg, sizeof(uimsg));                  GetWindowText(dlg, uimsg, sizeof(uimsg));
1263                  UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);                  UTIL_get_lang_msg("DLG_UNKNONWHOST_TITLE", pvar, uimsg);
1264                  SetWindowText(dlg, pvar->ts->UIMsg);                  SetWindowText(dlg, pvar->ts->UIMsg);
1265                  GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1266                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG", pvar, uimsg);
1267                  SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1268                  GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1269                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_WARNINIG2", pvar, uimsg);
1270                  SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1271                  GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1272                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_FINGERPRINT", pvar, uimsg);
1273                  SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1274                  GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1275                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);                  UTIL_get_lang_msg("DLG_UNKNOWNHOST_ADD", pvar, uimsg);
1276                  SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1277                  GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1278                  UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);                  UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1279                  SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1280                  GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1281                  UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);                  UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1282                  SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1283    
1284                  init_hosts_dlg(pvar, dlg);                  init_hosts_dlg(pvar, dlg);
1285    
1286                  font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);                  font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1287                  GetObject(font, sizeof(LOGFONT), &logfont);                  GetObject(font, sizeof(LOGFONT), &logfont);
1288                  if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {                  if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsAddFont, pvar)) {
1289                          SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1290                          SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1291                          SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1292                          SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_FINGER_PRINT, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1293                          SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1294                          SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1295                          SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsAddFont, MAKELPARAM(TRUE,0));
1296                  }                  }
1297                  else {                  else {
1298                          DlgHostsAddFont = NULL;                          DlgHostsAddFont = NULL;
1299                  }                  }
1300    
1301                  // add host check boxにチェックをデフォルトで入れておく                  // add host check boxにチェックをデフォルトで入れておく
1302                  SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);                  SendMessage(GetDlgItem(dlg, IDC_ADDTOKNOWNHOSTS), BM_SETCHECK, BST_CHECKED, 0);
1303    
1304                  return TRUE;                    /* because we do not set the focus */                  return TRUE;                    /* because we do not set the focus */
1305    
1306          case WM_COMMAND:          case WM_COMMAND:
1307                  pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);                  pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1308    
1309                  switch (LOWORD(wParam)) {                  switch (LOWORD(wParam)) {
1310                  case IDC_CONTINUE:                  case IDC_CONTINUE:
1311                          if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {                          if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1312                                  add_host_key(pvar);                                  add_host_key(pvar);
1313                          }                          }
1314    
1315                          if (SSHv1(pvar)) {                          if (SSHv1(pvar)) {
1316                                  SSH_notify_host_OK(pvar);                                  SSH_notify_host_OK(pvar);
1317                          } else { // SSH2                          } else { // SSH2
1318                                  // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。                                  // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。
1319                          }                          }
1320    
1321                          pvar->hosts_state.hosts_dialog = NULL;                          pvar->hosts_state.hosts_dialog = NULL;
1322    
1323                          EndDialog(dlg, 1);                          EndDialog(dlg, 1);
1324    
1325                          if (DlgHostsAddFont != NULL) {                          if (DlgHostsAddFont != NULL) {
1326                                  DeleteObject(DlgHostsAddFont);                                  DeleteObject(DlgHostsAddFont);
1327                          }                          }
1328    
1329                          return TRUE;                          return TRUE;
1330    
1331                  case IDCANCEL:                  /* kill the connection */                  case IDCANCEL:                  /* kill the connection */
1332                          pvar->hosts_state.hosts_dialog = NULL;                          pvar->hosts_state.hosts_dialog = NULL;
1333                          notify_closed_connection(pvar);                          notify_closed_connection(pvar);
1334                          EndDialog(dlg, 0);                          EndDialog(dlg, 0);
1335    
1336                          if (DlgHostsAddFont != NULL) {                          if (DlgHostsAddFont != NULL) {
1337                                  DeleteObject(DlgHostsAddFont);                                  DeleteObject(DlgHostsAddFont);
1338                          }                          }
1339    
1340                          return TRUE;                          return TRUE;
1341    
1342                  default:                  default:
1343                          return FALSE;                          return FALSE;
1344                  }                  }
1345    
1346          default:          default:
1347                  return FALSE;                  return FALSE;
1348          }          }
1349  }  }
1350    
1351  //  //
1352  // 置き換え時の確認ダイアログを分離  // 置き換え時の確認ダイアログを分離
1353  //  //
1354  static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,  static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
1355                                              LPARAM lParam)                                              LPARAM lParam)
1356  {  {
1357          PTInstVar pvar;          PTInstVar pvar;
1358          LOGFONT logfont;          LOGFONT logfont;
1359          HFONT font;          HFONT font;
1360          char uimsg[MAX_UIMSG];          char uimsg[MAX_UIMSG];
1361    
1362          switch (msg) {          switch (msg) {
1363          case WM_INITDIALOG:          case WM_INITDIALOG:
1364                  pvar = (PTInstVar) lParam;                  pvar = (PTInstVar) lParam;
1365                  pvar->hosts_state.hosts_dialog = dlg;                  pvar->hosts_state.hosts_dialog = dlg;
1366                  SetWindowLong(dlg, DWL_USER, lParam);                  SetWindowLong(dlg, DWL_USER, lParam);
1367    
1368                  // 追加・置き換えとも init_hosts_dlg を呼んでいるので、その前にセットする必要がある                  // 追加・置き換えとも init_hosts_dlg を呼んでいるので、その前にセットする必要がある
1369                  GetWindowText(dlg, uimsg, sizeof(uimsg));                  GetWindowText(dlg, uimsg, sizeof(uimsg));
1370                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_TITLE", pvar, uimsg);
1371                  SetWindowText(dlg, pvar->ts->UIMsg);                  SetWindowText(dlg, pvar->ts->UIMsg);
1372                  GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_HOSTWARNING, uimsg, sizeof(uimsg));
1373                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING", pvar, uimsg);
1374                  SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_HOSTWARNING, pvar->ts->UIMsg);
1375                  GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_HOSTWARNING2, uimsg, sizeof(uimsg));
1376                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_WARNING2", pvar, uimsg);
1377                  SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_HOSTWARNING2, pvar->ts->UIMsg);
1378                  GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_HOSTFINGERPRINT, uimsg, sizeof(uimsg));
1379                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_FINGERPRINT", pvar, uimsg);
1380                  SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_HOSTFINGERPRINT, pvar->ts->UIMsg);
1381                  GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, uimsg, sizeof(uimsg));
1382                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);                  UTIL_get_lang_msg("DLG_DIFFERENTHOST_REPLACE", pvar, uimsg);
1383                  SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_ADDTOKNOWNHOSTS, pvar->ts->UIMsg);
1384                  GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDC_CONTINUE, uimsg, sizeof(uimsg));
1385                  UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);                  UTIL_get_lang_msg("BTN_CONTINUE", pvar, uimsg);
1386                  SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDC_CONTINUE, pvar->ts->UIMsg);
1387                  GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));                  GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1388                  UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);                  UTIL_get_lang_msg("BTN_DISCONNECT", pvar, uimsg);
1389                  SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);                  SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1390    
1391                  init_hosts_dlg(pvar, dlg);                  init_hosts_dlg(pvar, dlg);
1392    
1393                  font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);                  font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1394                  GetObject(font, sizeof(LOGFONT), &logfont);                  GetObject(font, sizeof(LOGFONT), &logfont);
1395                  if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {                  if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgHostsReplaceFont, pvar)) {
1396                          SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_HOSTWARNING, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1397                          SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_HOSTWARNING2, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1398                          SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_HOSTFINGERPRINT, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1399                          SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_ADDTOKNOWNHOSTS, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1400                          SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDC_CONTINUE, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1401                          SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));                          SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostsReplaceFont, MAKELPARAM(TRUE,0));
1402                  }                  }
1403                  else {                  else {
1404                          DlgHostsReplaceFont = NULL;                          DlgHostsReplaceFont = NULL;
1405                  }                  }
1406    
1407                  // デフォルトでチェックは入れない                  // デフォルトでチェックは入れない
1408                  return TRUE;                    /* because we do not set the focus */                  return TRUE;                    /* because we do not set the focus */
1409    
1410          case WM_COMMAND:          case WM_COMMAND:
1411                  pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);                  pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
1412    
1413                  switch (LOWORD(wParam)) {                  switch (LOWORD(wParam)) {
1414                  case IDC_CONTINUE:                  case IDC_CONTINUE:
1415                          if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {                          if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) {
1416                                  add_host_key(pvar);                                  add_host_key(pvar);
1417                                  delete_different_key(pvar);                                  delete_different_key(pvar);
1418                          }                          }
1419    
1420                          if (SSHv1(pvar)) {                          if (SSHv1(pvar)) {
1421                                  SSH_notify_host_OK(pvar);                                  SSH_notify_host_OK(pvar);
1422                          } else { // SSH2                          } else { // SSH2
1423                                  // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。                                  // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。
1424                          }                          }
1425    
1426                          pvar->hosts_state.hosts_dialog = NULL;                          pvar->hosts_state.hosts_dialog = NULL;
1427    
1428                          EndDialog(dlg, 1);                          EndDialog(dlg, 1);
1429    
1430                          if (DlgHostsReplaceFont != NULL) {                          if (DlgHostsReplaceFont != NULL) {
1431                                  DeleteObject(DlgHostsReplaceFont);                                  DeleteObject(DlgHostsReplaceFont);
1432                          }                          }
1433    
1434                          return TRUE;                          return TRUE;
1435    
1436                  case IDCANCEL:                  /* kill the connection */                  case IDCANCEL:                  /* kill the connection */
1437                          pvar->hosts_state.hosts_dialog = NULL;                          pvar->hosts_state.hosts_dialog = NULL;
1438                          notify_closed_connection(pvar);                          notify_closed_connection(pvar);
1439                          EndDialog(dlg, 0);                          EndDialog(dlg, 0);
1440    
1441                          if (DlgHostsReplaceFont != NULL) {                          if (DlgHostsReplaceFont != NULL) {
1442                                  DeleteObject(DlgHostsReplaceFont);                                  DeleteObject(DlgHostsReplaceFont);
1443                          }                          }
1444    
1445                          return TRUE;                          return TRUE;
1446    
1447                  default:                  default:
1448                          return FALSE;                          return FALSE;
1449                  }                  }
1450    
1451          default:          default:
1452                  return FALSE;                  return FALSE;
1453          }          }
1454  }  }
1455    
1456  void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)  void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar)
1457  {  {
1458          if (pvar->hosts_state.hosts_dialog == NULL) {          if (pvar->hosts_state.hosts_dialog == NULL) {
1459                  HWND cur_active = GetActiveWindow();                  HWND cur_active = GetActiveWindow();
1460    
1461                  DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),                  DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST),
1462                                 cur_active != NULL ? cur_active : wnd,                                 cur_active != NULL ? cur_active : wnd,
1463                                 hosts_add_dlg_proc, (LPARAM) pvar);                                 hosts_add_dlg_proc, (LPARAM) pvar);
1464          }          }
1465  }  }
1466    
1467  void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)  void HOSTS_do_different_host_dialog(HWND wnd, PTInstVar pvar)
1468  {  {
1469          if (pvar->hosts_state.hosts_dialog == NULL) {          if (pvar->hosts_state.hosts_dialog == NULL) {
1470                  HWND cur_active = GetActiveWindow();                  HWND cur_active = GetActiveWindow();
1471    
1472                  DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),                  DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST),
1473                                 cur_active != NULL ? cur_active : wnd,                                 cur_active != NULL ? cur_active : wnd,
1474                                 hosts_replace_dlg_proc, (LPARAM) pvar);                                 hosts_replace_dlg_proc, (LPARAM) pvar);
1475          }          }
1476  }  }
1477    
1478  //  //
1479  // サーバから送られてきたホスト公開鍵の妥当性をチェックする  // サーバから送られてきたホスト公開鍵の妥当性をチェックする
1480  //  //
1481  // SSH2対応を追加 (2006.3.24 yutaka)  // SSH2対応を追加 (2006.3.24 yutaka)
1482  //  //
1483  BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)  BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key)
1484  {  {
1485          int found_different_key = 0;          int found_different_key = 0;
1486    
1487          // すでに known_hosts ファイルからホスト公開鍵を読み込んでいるなら、それと比較する。          // すでに known_hosts ファイルからホスト公開鍵を読み込んでいるなら、それと比較する。
1488          if (pvar->hosts_state.prefetched_hostname != NULL          if (pvar->hosts_state.prefetched_hostname != NULL
1489           && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0           && _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0
1490           && match_key(pvar, key)) {           && match_key(pvar, key)) {
1491    
1492                  if (SSHv1(pvar)) {                  if (SSHv1(pvar)) {
1493                          SSH_notify_host_OK(pvar);                          SSH_notify_host_OK(pvar);
1494                  } else {                  } else {
1495                          // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。                          // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。
1496                  }                  }
1497                  return TRUE;                  return TRUE;
1498          }          }
1499    
1500          // 先読みされていない場合は、この時点でファイルから読み込む          // 先読みされていない場合は、この時点でファイルから読み込む
1501          if (begin_read_host_files(pvar, 0)) {          if (begin_read_host_files(pvar, 0)) {
1502                  do {                  do {
1503                          if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {                          if (!read_host_key(pvar, hostname, tcpport, 0, 0)) {
1504                                  break;                                  break;
1505                          }                          }
1506    
1507                          if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {                          if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) {
1508                                  if (match_key(pvar, key)) {                                  if (match_key(pvar, key)) {
1509                                          finish_read_host_files(pvar, 0);                                          finish_read_host_files(pvar, 0);
1510                                          // すべてのエントリを参照して、合致するキーが見つかったら戻る。                                          // すべてのエントリを参照して、合致するキーが見つかったら戻る。
1511                                          // SSH2の場合はここでは何もしない。(2006.3.29 yutaka)                                          // SSH2の場合はここでは何もしない。(2006.3.29 yutaka)
1512                                          if (SSHv1(pvar)) {                                          if (SSHv1(pvar)) {
1513                                                  SSH_notify_host_OK(pvar);                                                  SSH_notify_host_OK(pvar);
1514                                          } else {                                          } else {
1515                                                  // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。                                                  // SSH2ではあとで SSH_notify_host_OK() を呼ぶ。
1516                                          }                                          }
1517                                          return TRUE;                                          return TRUE;
1518                                  } else {                                  } else {
1519                                          // キーは known_hosts に見つかったが、キーの内容が異なる。                                          // キーは known_hosts に見つかったが、キーの内容が異なる。
1520                                          found_different_key = 1;                                          found_different_key = 1;
1521                                  }                                  }
1522                          }                          }
1523                  } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC);  // キーが見つかっている間はループする                  } while (pvar->hosts_state.hostkey.type != KEY_UNSPEC);  // キーが見つかっている間はループする
1524    
1525                  finish_read_host_files(pvar, 0);                  finish_read_host_files(pvar, 0);
1526          }          }
1527    
1528    
1529          // known_hosts に存在しないキーはあとでファイルへ書き込むために、ここで保存しておく。          // known_hosts に存在しないキーはあとでファイルへ書き込むために、ここで保存しておく。
1530          pvar->hosts_state.hostkey.type = key->type;          pvar->hosts_state.hostkey.type = key->type;
1531          if (key->type == KEY_RSA1) { // SSH1          if (key->type == KEY_RSA1) { // SSH1
1532                  pvar->hosts_state.hostkey.bits = key->bits;                  pvar->hosts_state.hostkey.bits = key->bits;
1533                  pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);                  pvar->hosts_state.hostkey.exp = copy_mp_int(key->exp);
1534                  pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);                  pvar->hosts_state.hostkey.mod = copy_mp_int(key->mod);
1535    
1536          } else if (key->type == KEY_RSA) { // SSH2 RSA          } else if (key->type == KEY_RSA) { // SSH2 RSA
1537                  pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);                  pvar->hosts_state.hostkey.rsa = duplicate_RSA(key->rsa);
1538    
1539          } else { // SSH2 DSA          } else { // SSH2 DSA
1540                  pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);                  pvar->hosts_state.hostkey.dsa = duplicate_DSA(key->dsa);
1541    
1542          }          }
1543          free(pvar->hosts_state.prefetched_hostname);          free(pvar->hosts_state.prefetched_hostname);
1544          pvar->hosts_state.prefetched_hostname = _strdup(hostname);          pvar->hosts_state.prefetched_hostname = _strdup(hostname);
1545    
1546          // known_hostsダイアログは同期的に表示させ、この時点においてユーザに確認          // known_hostsダイアログは同期的に表示させ、この時点においてユーザに確認
1547          // させる必要があるため、直接コールに変更する。          // させる必要があるため、直接コールに変更する。
1548          // これによりknown_hostsの確認を待たずに、サーバへユーザ情報を送ってしまう問題を回避する。          // これによりknown_hostsの確認を待たずに、サーバへユーザ情報を送ってしまう問題を回避する。
1549          // (2007.10.1 yutaka)          // (2007.10.1 yutaka)
1550          if (found_different_key) {          if (found_different_key) {
1551  #if 0  #if 0
1552                  PostMessage(pvar->NotificationWindow, WM_COMMAND,                  PostMessage(pvar->NotificationWindow, WM_COMMAND,
1553                              ID_SSHDIFFERENTHOST, 0);                              ID_SSHDIFFERENTHOST, 0);
1554  #else  #else
1555                  HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);                  HOSTS_do_different_host_dialog(pvar->NotificationWindow, pvar);
1556  #endif  #endif
1557          } else {          } else {
1558  #if 0  #if 0
1559                  PostMessage(pvar->NotificationWindow, WM_COMMAND,                  PostMessage(pvar->NotificationWindow, WM_COMMAND,
1560                              ID_SSHUNKNOWNHOST, 0);                              ID_SSHUNKNOWNHOST, 0);
1561  #else  #else
1562                  HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);                  HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar);
1563  #endif  #endif
1564    
1565          }          }
1566    
1567          return TRUE;          return TRUE;
1568  }  }
1569    
1570  void HOSTS_notify_disconnecting(PTInstVar pvar)  void HOSTS_notify_disconnecting(PTInstVar pvar)
1571  {  {
1572          if (pvar->hosts_state.hosts_dialog != NULL) {          if (pvar->hosts_state.hosts_dialog != NULL) {
1573                  PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,                  PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL,
1574                              0);                              0);
1575                  /* the main window might not go away if it's not enabled. (see vtwin.cpp) */                  /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1576                  EnableWindow(pvar->NotificationWindow, TRUE);                  EnableWindow(pvar->NotificationWindow, TRUE);
1577          }          }
1578  }  }
1579    
1580  void HOSTS_end(PTInstVar pvar)  void HOSTS_end(PTInstVar pvar)
1581  {  {
1582          int i;          int i;
1583    
1584          free(pvar->hosts_state.prefetched_hostname);          free(pvar->hosts_state.prefetched_hostname);
1585  #if 0  #if 0
1586          free(pvar->hosts_state.key_exp);          free(pvar->hosts_state.key_exp);
1587          free(pvar->hosts_state.key_mod);          free(pvar->hosts_state.key_mod);
1588  #else  #else
1589          init_hostkey(&pvar->hosts_state.hostkey);          init_hostkey(&pvar->hosts_state.hostkey);
1590  #endif  #endif
1591    
1592          if (pvar->hosts_state.file_names != NULL) {          if (pvar->hosts_state.file_names != NULL) {
1593                  for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {                  for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) {
1594                          free(pvar->hosts_state.file_names[i]);                          free(pvar->hosts_state.file_names[i]);
1595                  }                  }
1596                  free(pvar->hosts_state.file_names);                  free(pvar->hosts_state.file_names);
1597          }          }
1598  }  }

Legend:
Removed from v.3221  
changed lines
  Added in v.3227

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