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

Legend:
Removed from v.3003  
changed lines
  Added in v.6771

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