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 3130 by doda, Fri May 23 05:04:09 2008 UTC trunk/ttssh2/ttxssh/pkt.c revision 6841 by doda, Tue Jul 4 15:02:28 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.   * (C) 2004-2017 TeraTerm Project
4     * All rights reserved.
5  Redistribution and use in source and binary forms, with or without modification,   *
6  are permitted provided that the following conditions are met:   * Redistribution and use in source and binary forms, with or without
7     * modification, are permitted provided that the following conditions
8  Redistributions of source code must retain the above copyright notice, this list of   * are met:
9  conditions and the following disclaimer.   *
10     * 1. Redistributions of source code must retain the above copyright
11  Redistributions in binary form must reproduce the above copyright notice, this list   *    notice, this list of conditions and the following disclaimer.
12  of conditions and the following disclaimer in the documentation and/or other materials   * 2. Redistributions in binary form must reproduce the above copyright
13  provided with the distribution.   *    notice, this list of conditions and the following disclaimer in the
14     *    documentation and/or other materials provided with the distribution.
15  The name of Robert O'Callahan may not be used to endorse or promote products derived from   * 3. The name of the author may not be used to endorse or promote products
16  this software without specific prior written permission.   *    derived from 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 AUTHORS ``AS IS'' AND ANY EXPRESS OR
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES   * 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.
21  THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  */   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28     */
29  /*  
30  This code is copyright (C) 1998-1999 Robert O'Callahan.  /*
31  See LICENSE.TXT for the license.  This code is copyright (C) 1998-1999 Robert O'Callahan.
32  */  See LICENSE.TXT for the license.
33    */
34  #include "ttxssh.h"  
35  #include "util.h"  #include "ttxssh.h"
36    #include "util.h"
37  //#define READAMOUNT 60000  #include "pkt.h"
38  // 60000 -> 65536 へ拡張。SSH2ではwindow制御を行うため、SSH2のwindow sizeと  
39  // 合わせておく必要がある。(2004.10.17 yutaka)  //#define READAMOUNT 60000
40  //#define READAMOUNT 65536  // 60000 -> 65536 へ拡張。SSH2ではwindow制御を行うため、SSH2のwindow sizeと
41  // 65536 -> 131072 へ拡張。(2007.10.29 maya)  // 合わせておく必要がある。(2004.10.17 yutaka)
42  #define READAMOUNT CHAN_SES_WINDOW_DEFAULT  //#define READAMOUNT 65536
43    // 65536 -> 131072 へ拡張。(2007.10.29 maya)
44  void PKT_init(PTInstVar pvar)  #define READAMOUNT CHAN_SES_WINDOW_DEFAULT
45  {  
46          buf_create(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);  void PKT_init(PTInstVar pvar)
47          pvar->pkt_state.datastart = 0;  {
48          pvar->pkt_state.datalen = 0;          buf_create(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);
49          pvar->pkt_state.seen_server_ID = FALSE;          pvar->pkt_state.datastart = 0;
50          pvar->pkt_state.seen_newline = FALSE;          pvar->pkt_state.datalen = 0;
51          pvar->pkt_state.predecrypted_packet = FALSE;          pvar->pkt_state.seen_server_ID = FALSE;
52  }          pvar->pkt_state.seen_newline = FALSE;
53            pvar->pkt_state.predecrypted_packet = FALSE;
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. */  
56  static int recv_data(PTInstVar pvar, unsigned long up_to_amount)  /* Read some data, leave no more than up_to_amount bytes in the buffer,
57  {     return the number of bytes read or -1 on error or blocking. */
58          int amount_read;  static int recv_data(PTInstVar pvar, unsigned long up_to_amount)
59    {
60          /* Shuffle data to the start of the buffer */          int amount_read;
61          if (pvar->pkt_state.datastart != 0) {  
62                  memmove(pvar->pkt_state.buf,          /* Shuffle data to the start of the buffer */
63                          pvar->pkt_state.buf + pvar->pkt_state.datastart,          if (pvar->pkt_state.datastart != 0) {
64                          pvar->pkt_state.datalen);                  memmove(pvar->pkt_state.buf,
65                  pvar->pkt_state.datastart = 0;                          pvar->pkt_state.buf + pvar->pkt_state.datastart,
66          }                          pvar->pkt_state.datalen);
67                    pvar->pkt_state.datastart = 0;
68          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,          }
69                          up_to_amount);  
70            buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,
71          _ASSERT(pvar->pkt_state.buf != NULL);                          up_to_amount);
72    
73          amount_read = (pvar->Precv) (pvar->socket,          _ASSERT(pvar->pkt_state.buf != NULL);
74                                       pvar->pkt_state.buf +  
75                                       pvar->pkt_state.datalen,          amount_read = (pvar->Precv) (pvar->socket,
76                                       up_to_amount - pvar->pkt_state.datalen,                                       pvar->pkt_state.buf +
77                                       0);                                       pvar->pkt_state.datalen,
78                                         up_to_amount - pvar->pkt_state.datalen,
79          if (amount_read > 0) {                                       0);
80                  /* Update seen_newline if necessary */  
81                  if (!pvar->pkt_state.seen_server_ID          if (amount_read > 0) {
82                   && !pvar->pkt_state.seen_newline) {                  /* Update seen_newline if necessary */
83                          int i;                  if (!pvar->pkt_state.seen_server_ID
84                     && !pvar->pkt_state.seen_newline) {
85                          for (i = 0; i < amount_read; i++) {                          int i;
86                                  if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] ==  
87                                      '\n') {                          for (i = 0; i < amount_read; i++) {
88                                          pvar->pkt_state.seen_newline = 1;                                  if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] ==
89                                  }                                      '\n') {
90                          }                                          pvar->pkt_state.seen_newline = 1;
91                  }                                  }
92                            }
93                  pvar->pkt_state.datalen += amount_read;                  }
94          }  
95                    pvar->pkt_state.datalen += amount_read;
96          return amount_read;          }
97  }  
98            return amount_read;
99    }
100  // 改行コードが出てくるまで読む  
101  static int recv_line_data(PTInstVar pvar)  
102  {  // 改行コードが出てくるまで読む
103          int amount_read;  static int recv_line_data(PTInstVar pvar)
104          char buf[256];  {
105          size_t up_to_amount = sizeof(buf);          int amount_read;
106          int i;          char buf[256];
107            size_t up_to_amount = sizeof(buf);
108          /* Shuffle data to the start of the buffer */          int i;
109          if (pvar->pkt_state.datastart != 0) {  
110                  memmove(pvar->pkt_state.buf,          /* Shuffle data to the start of the buffer */
111                          pvar->pkt_state.buf + pvar->pkt_state.datastart,          if (pvar->pkt_state.datastart != 0) {
112                          pvar->pkt_state.datalen);                  memmove(pvar->pkt_state.buf,
113                  pvar->pkt_state.datastart = 0;                          pvar->pkt_state.buf + pvar->pkt_state.datastart,
114          }                          pvar->pkt_state.datalen);
115                    pvar->pkt_state.datastart = 0;
116          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,          }
117                          up_to_amount);  
118            buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,
119          for (i = 0 ; i < (int)up_to_amount ; i++) {                          up_to_amount);
120                  amount_read = (pvar->Precv) (pvar->socket,  
121                                               &buf[i], 1, 0);          for (i = 0 ; i < (int)up_to_amount ; i++) {
122                  if (amount_read != 1) {                  amount_read = (pvar->Precv) (pvar->socket,
123                          return 0; // error                                               &buf[i], 1, 0);
124                  }                  if (amount_read != 1) {
125                            return 0; // error
126                  pvar->pkt_state.datalen += amount_read;                  }
127    
128                  if (buf[i] == '\n') { // 0x0a                  pvar->pkt_state.datalen += amount_read;
129                          buf[i+1] = 0;  
130                          break;                  if (buf[i] == '\n') { // 0x0a
131                  }                          buf[i+1] = 0;
132          }                          break;
133          amount_read = i + 1; // 読み込みサイズ(LFも含む)                  }
134          memcpy(pvar->pkt_state.buf, buf, amount_read);          }
135            amount_read = i + 1; // 読み込みサイズ(LFも含む)
136          pvar->pkt_state.seen_newline = 1;          memcpy(pvar->pkt_state.buf, buf, amount_read);
137    
138          return amount_read;          pvar->pkt_state.seen_newline = 1;
139  }  
140            return amount_read;
141    }
142  /* This function does two things:  
143     -- reads data from the sshd and feeds the SSH protocol packets to ssh.c  
144     -- copies any available decrypted session data into the application buffer  /* This function does two things:
145  */     -- reads data from the sshd and feeds the SSH protocol packets to ssh.c
146  int PKT_recv(PTInstVar pvar, char FAR * buf, int buflen)     -- copies any available decrypted session data into the application buffer
147  {  */
148          int amount_in_buf = 0;  int PKT_recv(PTInstVar pvar, char *buf, int buflen)
149          BOOL connection_closed = FALSE;  {
150            int amount_in_buf = 0;
151          while (SSH_is_any_payload(pvar) ? buflen > 0 : !connection_closed) {          BOOL connection_closed = FALSE;
152                  if (SSH_is_any_payload(pvar)) {  
153                          /* ssh.c has some session data for us to give to TeraTerm. */          while (SSH_is_any_payload(pvar) ? buflen > 0 : !connection_closed) {
154                          int grabbed = SSH_extract_payload(pvar, buf, buflen);                  if (SSH_is_any_payload(pvar)) {
155                            /* ssh.c has some session data for us to give to Tera Term. */
156                          amount_in_buf += grabbed;                          int grabbed = SSH_extract_payload(pvar, buf, buflen);
157                          buf += grabbed;  
158                          buflen -= grabbed;                          amount_in_buf += grabbed;
159                            buf += grabbed;
160                  } else if (!pvar->pkt_state.seen_server_ID &&                          buflen -= grabbed;
161                             (pvar->pkt_state.seen_newline  
162                              || pvar->pkt_state.datalen >= 255)) {                  } else if (!pvar->pkt_state.seen_server_ID &&
163                          /* We're looking for the initial ID string and either we've seen the                             (pvar->pkt_state.seen_newline
164                             terminating newline, or we've exceeded the limit at which we should see                              || pvar->pkt_state.datalen >= 255)) {
165                             a newline. */                          /* We're looking for the initial ID string and either we've seen the
166                          unsigned int i;                             terminating newline, or we've exceeded the limit at which we should see
167                               a newline. */
168                          for (i = 0;                          unsigned int i;
169                               pvar->pkt_state.buf[i] != '\n'  
170                               && i < pvar->pkt_state.datalen; i++) {                          for (i = 0;
171                          }                               pvar->pkt_state.buf[i] != '\n'
172                          if (pvar->pkt_state.buf[i] == '\n') {                               && i < pvar->pkt_state.datalen; i++) {
173                                  i++;                          }
174                          }                          if (pvar->pkt_state.buf[i] == '\n') {
175                                    i++;
176                          // SSHサーバのバージョンチェックを行う                          }
177                          if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {  
178                                  pvar->pkt_state.seen_server_ID = 1;                          // SSHサーバのバージョンチェックを行う
179                            if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {
180                                  if (SSHv1(pvar)) {                                  pvar->pkt_state.seen_server_ID = 1;
181    
182                                  } else { // for SSH2(yutaka)                                  if (SSHv1(pvar)) {
183                                          // send Key Exchange Init  
184                                          SSH2_send_kexinit(pvar);                                  } else { // for SSH2(yutaka)
185                                  }                                          // send Key Exchange Init
186                                            SSH2_send_kexinit(pvar);
187                          } else {                                  }
188                                  // reset flag to re-read server ID (2008.1.24 yutaka)  
189                                  pvar->pkt_state.seen_newline = 0;                          } else {
190                                    // reset flag to re-read server ID (2008.1.24 yutaka)
191                          }                                  pvar->pkt_state.seen_newline = 0;
192    
193                          pvar->pkt_state.datastart += i;                          }
194                          pvar->pkt_state.datalen -= i;  
195                            pvar->pkt_state.datastart += i;
196                  } else if (pvar->pkt_state.seen_server_ID                          pvar->pkt_state.datalen -= i;
197                             && pvar->pkt_state.datalen >=  
198                             (unsigned int) SSH_get_min_packet_size(pvar)) {                  } else if (pvar->pkt_state.seen_server_ID
199                          char FAR *data =                             && pvar->pkt_state.datalen >=
200                                  pvar->pkt_state.buf + pvar->pkt_state.datastart;                             (unsigned int) SSH_get_min_packet_size(pvar)) {
201                          uint32 padding;                          char *data =
202                          uint32 pktsize;                                  pvar->pkt_state.buf + pvar->pkt_state.datastart;
203                          uint32 total_packet_size;                          uint32 padding;
204                            uint32 pktsize;
205                          //debug_print(10, data, pvar->pkt_state.datalen);                          uint32 total_packet_size;
206    
207                          // SSH2なら暗号化パケットの一部を復号化する。                          //debug_print(10, data, pvar->pkt_state.datalen);
208                          if (!pvar->pkt_state.predecrypted_packet) {  
209                                  //DEBUG_PRINT_TO_FILE(0, data, pvar->pkt_state.datalen);                          // 暗号化パケットの一部を復号化する。
210                                  SSH_predecrpyt_packet(pvar, data);                          if (!pvar->pkt_state.predecrypted_packet) {
211                                    SSH_predecrpyt_packet(pvar, data);
212                                  if (SSHv1(pvar)) {                                  pvar->pkt_state.predecrypted_packet = TRUE;
213                                          pvar->pkt_state.predecrypted_packet = TRUE;                          }
214                                  } else { // for SSH2(yutaka)  
215                                          // do nothing                          if (SSHv1(pvar)) {
216                                          pvar->pkt_state.predecrypted_packet = TRUE;                                  uint32 realpktsize = get_uint32_MSBfirst(data);
217                                  }  
218                          }                                  padding = 8 - (realpktsize % 8);
219                                    pktsize = realpktsize + padding;
220                          if (SSHv1(pvar)) {                          } else {
221                                  uint32 realpktsize = get_uint32_MSBfirst(data);                                  // SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。
222                                    pktsize = get_uint32_MSBfirst(data);
223                                  padding = 8 - (realpktsize % 8);                                  padding = (unsigned char) data[4];
224                                  pktsize = realpktsize + padding;                          }
225                          } else {  
226                                  // SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。
227                                  pktsize = get_uint32_MSBfirst(data);                          // +4は、SSHペイロードのサイズを格納している部分(int型)。
228                                  padding = (unsigned char) data[4];                          total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);
229                          }  
230                            if (total_packet_size <= pvar->pkt_state.datalen) {
231                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。                                  /* the data must be 4 byte aligned. */
232                          // +4は、SSHペイロードのサイズを格納している部分(int型)。                                  SSH_handle_packet(pvar, data, pktsize, padding);
233                          total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);                                  pvar->pkt_state.predecrypted_packet = FALSE;
234    
235                          if (total_packet_size <= pvar->pkt_state.datalen) {                                  pvar->pkt_state.datastart += total_packet_size;
236                                  /* the data must be 4 byte aligned. */                                  pvar->pkt_state.datalen -= total_packet_size;
237                                  SSH_handle_packet(pvar, data, pktsize, padding);  
238                                  pvar->pkt_state.predecrypted_packet = FALSE;                          } else if (total_packet_size > PACKET_MAX_SIZE) {
239                                    // 4MBを超える巨大なパケットが届いたら、異常終了する。
240                                  pvar->pkt_state.datastart += total_packet_size;                                  // 実際にはデータ化けで復号失敗時に、誤認識することが多い。
241                                  pvar->pkt_state.datalen -= total_packet_size;                                  UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,
242                                                      "Oversized packet received from server; connection will close.");
243                          } else if (total_packet_size > 4 * 1024 * 1024) {                                  notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
244                                  // 4MBを超える巨大なパケットが届いたら、異常終了する。                          } else {
245                                  // 実際にはデータ化けで復号失敗時に、誤認識することが多い。                                  int amount_read =
246                                  UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,                                          recv_data(pvar, max(total_packet_size, READAMOUNT));
247                                                                    "Oversized packet received from server; connection will close.");  
248                                  notify_fatal_error(pvar, pvar->ts->UIMsg);                                  if (amount_read == SOCKET_ERROR) {
249                          } else {                                          if (amount_in_buf == 0) {
250                                  int amount_read =                                                  return SOCKET_ERROR;
251                                          recv_data(pvar, max(total_packet_size, READAMOUNT));                                          } else {
252                                                    return amount_in_buf;
253                                  if (amount_read == SOCKET_ERROR) {                                          }
254                                          if (amount_in_buf == 0) {                                  } else {
255                                                  return SOCKET_ERROR;                                          if (amount_read == 0) {
256                                          } else {                                                  connection_closed = TRUE;
257                                                  return amount_in_buf;                                          }
258                                          }                                  }
259                                  } else {                          }
260                                          if (amount_read == 0) {  
261                                                  connection_closed = TRUE;  
262                                          }                  } else {
263                                  }                          // パケットの受信(最大60KB)
264                          }                          int amount_read;
265    
266                            if (pvar->pkt_state.seen_server_ID == 0) {
267                  } else {                                  //amount_read = recv_line_data(pvar);
268                          // パケットの受信(最大60KB)                                  amount_read = recv_data(pvar, READAMOUNT);
269                          int amount_read;  
270                            } else {
271                          if (pvar->pkt_state.seen_server_ID == 0) {                                  amount_read = recv_data(pvar, READAMOUNT);
272                                  //amount_read = recv_line_data(pvar);  
273                                  amount_read = recv_data(pvar, READAMOUNT);                          }
274    
275                          } else {                          if (amount_read == SOCKET_ERROR) {
276                                  amount_read = recv_data(pvar, READAMOUNT);                                  if (amount_in_buf == 0) {
277                                            return SOCKET_ERROR;
278                          }                                  } else {
279                                            return amount_in_buf;
280                          if (amount_read == SOCKET_ERROR) {                                  }
281                                  if (amount_in_buf == 0) {                          } else if (amount_read == 0) {
282                                          return SOCKET_ERROR;                                  connection_closed = TRUE;
283                                  } else {                          }
284                                          return amount_in_buf;                  }
285                                  }  
286                          } else if (amount_read == 0) {                  if (pvar->fatal_error) {
287                                  connection_closed = TRUE;                          return amount_in_buf;
288                          }                  }
289                  }          }
290    
291                  if (pvar->fatal_error) {          if (SSH_is_any_payload(pvar)) {
292                          return amount_in_buf;                  PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
293                  }                              pvar->socket, MAKELPARAM(FD_READ, 0));
294          }          }
295    
296          if (SSH_is_any_payload(pvar)) {          return amount_in_buf;
297                  PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,  }
298                              pvar->socket, MAKELPARAM(FD_READ, 0));  
299          }  void PKT_end(PTInstVar pvar)
300    {
301          return amount_in_buf;          buf_destroy(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);
302  }  }
   
 void PKT_end(PTInstVar pvar)  
 {  
         buf_destroy(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);  
 }  

Legend:
Removed from v.3130  
changed lines
  Added in v.6841

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