Develop and Download Open Source Software

Browse Subversion Repository

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

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

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

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

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