Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

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

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

revision 3226 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 "pkt.h"  #include "pkt.h"
37    
38  //#define READAMOUNT 60000  //#define READAMOUNT 60000
39  // 60000 -> 65536 へ拡張。SSH2ではwindow制御を行うため、SSH2のwindow sizeと  // 60000 -> 65536 へ拡張。SSH2ではwindow制御を行うため、SSH2のwindow sizeと
40  // 合わせておく必要がある。(2004.10.17 yutaka)  // 合わせておく必要がある。(2004.10.17 yutaka)
41  //#define READAMOUNT 65536  //#define READAMOUNT 65536
42  // 65536 -> 131072 へ拡張。(2007.10.29 maya)  // 65536 -> 131072 へ拡張。(2007.10.29 maya)
43  #define READAMOUNT CHAN_SES_WINDOW_DEFAULT  #define READAMOUNT CHAN_SES_WINDOW_DEFAULT
44    
45  void PKT_init(PTInstVar pvar)  void PKT_init(PTInstVar pvar)
46  {  {
47          buf_create(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);          buf_create(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);
48          pvar->pkt_state.datastart = 0;          pvar->pkt_state.datastart = 0;
49          pvar->pkt_state.datalen = 0;          pvar->pkt_state.datalen = 0;
50          pvar->pkt_state.seen_server_ID = FALSE;          pvar->pkt_state.seen_server_ID = FALSE;
51          pvar->pkt_state.seen_newline = FALSE;          pvar->pkt_state.seen_newline = FALSE;
52          pvar->pkt_state.predecrypted_packet = FALSE;          pvar->pkt_state.predecrypted_packet = FALSE;
53  }  }
54    
55  /* Read some data, leave no more than up_to_amount bytes in the buffer,  /* Read some data, leave no more than up_to_amount bytes in the buffer,
56     return the number of bytes read or -1 on error or blocking. */     return the number of bytes read or -1 on error or blocking. */
57  static int recv_data(PTInstVar pvar, unsigned long up_to_amount)  static int recv_data(PTInstVar pvar, unsigned long up_to_amount)
58  {  {
59          int amount_read;          int amount_read;
60    
61          /* Shuffle data to the start of the buffer */          /* Shuffle data to the start of the buffer */
62          if (pvar->pkt_state.datastart != 0) {          if (pvar->pkt_state.datastart != 0) {
63                  memmove(pvar->pkt_state.buf,                  memmove(pvar->pkt_state.buf,
64                          pvar->pkt_state.buf + pvar->pkt_state.datastart,                          pvar->pkt_state.buf + pvar->pkt_state.datastart,
65                          pvar->pkt_state.datalen);                          pvar->pkt_state.datalen);
66                  pvar->pkt_state.datastart = 0;                  pvar->pkt_state.datastart = 0;
67          }          }
68    
69          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,
70                          up_to_amount);                          up_to_amount);
71    
72          _ASSERT(pvar->pkt_state.buf != NULL);          _ASSERT(pvar->pkt_state.buf != NULL);
73    
74          amount_read = (pvar->Precv) (pvar->socket,          amount_read = (pvar->Precv) (pvar->socket,
75                                       pvar->pkt_state.buf +                                       pvar->pkt_state.buf +
76                                       pvar->pkt_state.datalen,                                       pvar->pkt_state.datalen,
77                                       up_to_amount - pvar->pkt_state.datalen,                                       up_to_amount - pvar->pkt_state.datalen,
78                                       0);                                       0);
79    
80          if (amount_read > 0) {          if (amount_read > 0) {
81                  /* Update seen_newline if necessary */                  /* Update seen_newline if necessary */
82                  if (!pvar->pkt_state.seen_server_ID                  if (!pvar->pkt_state.seen_server_ID
83                   && !pvar->pkt_state.seen_newline) {                   && !pvar->pkt_state.seen_newline) {
84                          int i;                          int i;
85    
86                          for (i = 0; i < amount_read; i++) {                          for (i = 0; i < amount_read; i++) {
87                                  if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] ==                                  if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] ==
88                                      '\n') {                                      '\n') {
89                                          pvar->pkt_state.seen_newline = 1;                                          pvar->pkt_state.seen_newline = 1;
90                                  }                                  }
91                          }                          }
92                  }                  }
93    
94                  pvar->pkt_state.datalen += amount_read;                  pvar->pkt_state.datalen += amount_read;
95          }          }
96    
97          return amount_read;          return amount_read;
98  }  }
99    
100    
101  // 改行コードが出てくるまで読む  // 改行コードが出てくるまで読む
102  static int recv_line_data(PTInstVar pvar)  static int recv_line_data(PTInstVar pvar)
103  {  {
104          int amount_read;          int amount_read;
105          char buf[256];          char buf[256];
106          size_t up_to_amount = sizeof(buf);          size_t up_to_amount = sizeof(buf);
107          int i;          int i;
108    
109          /* Shuffle data to the start of the buffer */          /* Shuffle data to the start of the buffer */
110          if (pvar->pkt_state.datastart != 0) {          if (pvar->pkt_state.datastart != 0) {
111                  memmove(pvar->pkt_state.buf,                  memmove(pvar->pkt_state.buf,
112                          pvar->pkt_state.buf + pvar->pkt_state.datastart,                          pvar->pkt_state.buf + pvar->pkt_state.datastart,
113                          pvar->pkt_state.datalen);                          pvar->pkt_state.datalen);
114                  pvar->pkt_state.datastart = 0;                  pvar->pkt_state.datastart = 0;
115          }          }
116    
117          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,
118                          up_to_amount);                          up_to_amount);
119    
120          for (i = 0 ; i < (int)up_to_amount ; i++) {          for (i = 0 ; i < (int)up_to_amount ; i++) {
121                  amount_read = (pvar->Precv) (pvar->socket,                  amount_read = (pvar->Precv) (pvar->socket,
122                                               &buf[i], 1, 0);                                               &buf[i], 1, 0);
123                  if (amount_read != 1) {                  if (amount_read != 1) {
124                          return 0; // error                          return 0; // error
125                  }                  }
126    
127                  pvar->pkt_state.datalen += amount_read;                  pvar->pkt_state.datalen += amount_read;
128    
129                  if (buf[i] == '\n') { // 0x0a                  if (buf[i] == '\n') { // 0x0a
130                          buf[i+1] = 0;                          buf[i+1] = 0;
131                          break;                          break;
132                  }                  }
133          }          }
134          amount_read = i + 1; // 読み込みサイズ(LFも含む)          amount_read = i + 1; // 読み込みサイズ(LFも含む)
135          memcpy(pvar->pkt_state.buf, buf, amount_read);          memcpy(pvar->pkt_state.buf, buf, amount_read);
136    
137          pvar->pkt_state.seen_newline = 1;          pvar->pkt_state.seen_newline = 1;
138    
139          return amount_read;          return amount_read;
140  }  }
141    
142    
143  /* This function does two things:  /* This function does two things:
144     -- reads data from the sshd and feeds the SSH protocol packets to ssh.c     -- reads data from the sshd and feeds the SSH protocol packets to ssh.c
145     -- copies any available decrypted session data into the application buffer     -- copies any available decrypted session data into the application buffer
146  */  */
147  int PKT_recv(PTInstVar pvar, char FAR * buf, int buflen)  int PKT_recv(PTInstVar pvar, char FAR * buf, int buflen)
148  {  {
149          int amount_in_buf = 0;          int amount_in_buf = 0;
150          BOOL connection_closed = FALSE;          BOOL connection_closed = FALSE;
151    
152          while (SSH_is_any_payload(pvar) ? buflen > 0 : !connection_closed) {          while (SSH_is_any_payload(pvar) ? buflen > 0 : !connection_closed) {
153                  if (SSH_is_any_payload(pvar)) {                  if (SSH_is_any_payload(pvar)) {
154                          /* ssh.c has some session data for us to give to Tera Term. */                          /* ssh.c has some session data for us to give to Tera Term. */
155                          int grabbed = SSH_extract_payload(pvar, buf, buflen);                          int grabbed = SSH_extract_payload(pvar, buf, buflen);
156    
157                          amount_in_buf += grabbed;                          amount_in_buf += grabbed;
158                          buf += grabbed;                          buf += grabbed;
159                          buflen -= grabbed;                          buflen -= grabbed;
160    
161                  } else if (!pvar->pkt_state.seen_server_ID &&                  } else if (!pvar->pkt_state.seen_server_ID &&
162                             (pvar->pkt_state.seen_newline                             (pvar->pkt_state.seen_newline
163                              || pvar->pkt_state.datalen >= 255)) {                              || pvar->pkt_state.datalen >= 255)) {
164                          /* We're looking for the initial ID string and either we've seen the                          /* We're looking for the initial ID string and either we've seen the
165                             terminating newline, or we've exceeded the limit at which we should see                             terminating newline, or we've exceeded the limit at which we should see
166                             a newline. */                             a newline. */
167                          unsigned int i;                          unsigned int i;
168    
169                          for (i = 0;                          for (i = 0;
170                               pvar->pkt_state.buf[i] != '\n'                               pvar->pkt_state.buf[i] != '\n'
171                               && i < pvar->pkt_state.datalen; i++) {                               && i < pvar->pkt_state.datalen; i++) {
172                          }                          }
173                          if (pvar->pkt_state.buf[i] == '\n') {                          if (pvar->pkt_state.buf[i] == '\n') {
174                                  i++;                                  i++;
175                          }                          }
176    
177                          // SSHサーバのバージョンチェックを行う                          // SSHサーバのバージョンチェックを行う
178                          if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {                          if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {
179                                  pvar->pkt_state.seen_server_ID = 1;                                  pvar->pkt_state.seen_server_ID = 1;
180    
181                                  if (SSHv1(pvar)) {                                  if (SSHv1(pvar)) {
182    
183                                  } else { // for SSH2(yutaka)                                  } else { // for SSH2(yutaka)
184                                          // send Key Exchange Init                                          // send Key Exchange Init
185                                          SSH2_send_kexinit(pvar);                                          SSH2_send_kexinit(pvar);
186                                  }                                  }
187    
188                          } else {                          } else {
189                                  // reset flag to re-read server ID (2008.1.24 yutaka)                                  // reset flag to re-read server ID (2008.1.24 yutaka)
190                                  pvar->pkt_state.seen_newline = 0;                                  pvar->pkt_state.seen_newline = 0;
191    
192                          }                          }
193    
194                          pvar->pkt_state.datastart += i;                          pvar->pkt_state.datastart += i;
195                          pvar->pkt_state.datalen -= i;                          pvar->pkt_state.datalen -= i;
196    
197                  } else if (pvar->pkt_state.seen_server_ID                  } else if (pvar->pkt_state.seen_server_ID
198                             && pvar->pkt_state.datalen >=                             && pvar->pkt_state.datalen >=
199                             (unsigned int) SSH_get_min_packet_size(pvar)) {                             (unsigned int) SSH_get_min_packet_size(pvar)) {
200                          char FAR *data =                          char FAR *data =
201                                  pvar->pkt_state.buf + pvar->pkt_state.datastart;                                  pvar->pkt_state.buf + pvar->pkt_state.datastart;
202                          uint32 padding;                          uint32 padding;
203                          uint32 pktsize;                          uint32 pktsize;
204                          uint32 total_packet_size;                          uint32 total_packet_size;
205    
206                          //debug_print(10, data, pvar->pkt_state.datalen);                          //debug_print(10, data, pvar->pkt_state.datalen);
207    
208                          // SSH2なら暗号化パケットの一部を復号化する。                          // SSH2なら暗号化パケットの一部を復号化する。
209                          if (!pvar->pkt_state.predecrypted_packet) {                          if (!pvar->pkt_state.predecrypted_packet) {
210                                  //DEBUG_PRINT_TO_FILE(0, data, pvar->pkt_state.datalen);                                  //DEBUG_PRINT_TO_FILE(0, data, pvar->pkt_state.datalen);
211                                  SSH_predecrpyt_packet(pvar, data);                                  SSH_predecrpyt_packet(pvar, data);
212    
213                                  if (SSHv1(pvar)) {                                  if (SSHv1(pvar)) {
214                                          pvar->pkt_state.predecrypted_packet = TRUE;                                          pvar->pkt_state.predecrypted_packet = TRUE;
215                                  } else { // for SSH2(yutaka)                                  } else { // for SSH2(yutaka)
216                                          // do nothing                                          // do nothing
217                                          pvar->pkt_state.predecrypted_packet = TRUE;                                          pvar->pkt_state.predecrypted_packet = TRUE;
218                                  }                                  }
219                          }                          }
220    
221                          if (SSHv1(pvar)) {                          if (SSHv1(pvar)) {
222                                  uint32 realpktsize = get_uint32_MSBfirst(data);                                  uint32 realpktsize = get_uint32_MSBfirst(data);
223    
224                                  padding = 8 - (realpktsize % 8);                                  padding = 8 - (realpktsize % 8);
225                                  pktsize = realpktsize + padding;                                  pktsize = realpktsize + padding;
226                          } else {                          } else {
227                                  // SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。                                  // SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。
228                                  pktsize = get_uint32_MSBfirst(data);                                  pktsize = get_uint32_MSBfirst(data);
229                                  padding = (unsigned char) data[4];                                  padding = (unsigned char) data[4];
230                          }                          }
231    
232                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。
233                          // +4は、SSHペイロードのサイズを格納している部分(int型)。                          // +4は、SSHペイロードのサイズを格納している部分(int型)。
234                          total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);                          total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);
235    
236                          if (total_packet_size <= pvar->pkt_state.datalen) {                          if (total_packet_size <= pvar->pkt_state.datalen) {
237                                  /* the data must be 4 byte aligned. */                                  /* the data must be 4 byte aligned. */
238                                  SSH_handle_packet(pvar, data, pktsize, padding);                                  SSH_handle_packet(pvar, data, pktsize, padding);
239                                  pvar->pkt_state.predecrypted_packet = FALSE;                                  pvar->pkt_state.predecrypted_packet = FALSE;
240    
241                                  pvar->pkt_state.datastart += total_packet_size;                                  pvar->pkt_state.datastart += total_packet_size;
242                                  pvar->pkt_state.datalen -= total_packet_size;                                  pvar->pkt_state.datalen -= total_packet_size;
243    
244                          } else if (total_packet_size > PACKET_MAX_SIZE) {                          } else if (total_packet_size > PACKET_MAX_SIZE) {
245                                  // 4MBを超える巨大なパケットが届いたら、異常終了する。                                  // 4MBを超える巨大なパケットが届いたら、異常終了する。
246                                  // 実際にはデータ化けで復号失敗時に、誤認識することが多い。                                  // 実際にはデータ化けで復号失敗時に、誤認識することが多い。
247                                  UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,                                  UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,
248                                                                    "Oversized packet received from server; connection will close.");                                                                    "Oversized packet received from server; connection will close.");
249                                  notify_fatal_error(pvar, pvar->ts->UIMsg);                                  notify_fatal_error(pvar, pvar->ts->UIMsg);
250                          } else {                          } else {
251                                  int amount_read =                                  int amount_read =
252                                          recv_data(pvar, max(total_packet_size, READAMOUNT));                                          recv_data(pvar, max(total_packet_size, READAMOUNT));
253    
254                                  if (amount_read == SOCKET_ERROR) {                                  if (amount_read == SOCKET_ERROR) {
255                                          if (amount_in_buf == 0) {                                          if (amount_in_buf == 0) {
256                                                  return SOCKET_ERROR;                                                  return SOCKET_ERROR;
257                                          } else {                                          } else {
258                                                  return amount_in_buf;                                                  return amount_in_buf;
259                                          }                                          }
260                                  } else {                                  } else {
261                                          if (amount_read == 0) {                                          if (amount_read == 0) {
262                                                  connection_closed = TRUE;                                                  connection_closed = TRUE;
263                                          }                                          }
264                                  }                                  }
265                          }                          }
266    
267    
268                  } else {                  } else {
269                          // パケットの受信(最大60KB)                          // パケットの受信(最大60KB)
270                          int amount_read;                          int amount_read;
271    
272                          if (pvar->pkt_state.seen_server_ID == 0) {                          if (pvar->pkt_state.seen_server_ID == 0) {
273                                  //amount_read = recv_line_data(pvar);                                  //amount_read = recv_line_data(pvar);
274                                  amount_read = recv_data(pvar, READAMOUNT);                                  amount_read = recv_data(pvar, READAMOUNT);
275    
276                          } else {                          } else {
277                                  amount_read = recv_data(pvar, READAMOUNT);                                  amount_read = recv_data(pvar, READAMOUNT);
278    
279                          }                          }
280    
281                          if (amount_read == SOCKET_ERROR) {                          if (amount_read == SOCKET_ERROR) {
282                                  if (amount_in_buf == 0) {                                  if (amount_in_buf == 0) {
283                                          return SOCKET_ERROR;                                          return SOCKET_ERROR;
284                                  } else {                                  } else {
285                                          return amount_in_buf;                                          return amount_in_buf;
286                                  }                                  }
287                          } else if (amount_read == 0) {                          } else if (amount_read == 0) {
288                                  connection_closed = TRUE;                                  connection_closed = TRUE;
289                          }                          }
290                  }                  }
291    
292                  if (pvar->fatal_error) {                  if (pvar->fatal_error) {
293                          return amount_in_buf;                          return amount_in_buf;
294                  }                  }
295          }          }
296    
297          if (SSH_is_any_payload(pvar)) {          if (SSH_is_any_payload(pvar)) {
298                  PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,                  PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
299                              pvar->socket, MAKELPARAM(FD_READ, 0));                              pvar->socket, MAKELPARAM(FD_READ, 0));
300          }          }
301    
302          return amount_in_buf;          return amount_in_buf;
303  }  }
304    
305  void PKT_end(PTInstVar pvar)  void PKT_end(PTInstVar pvar)
306  {  {
307          buf_destroy(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);          buf_destroy(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);
308  }  }

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

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