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

revision 6841 by doda, Tue Jul 4 15:02:28 2017 UTC revision 6981 by doda, Sat Nov 25 15:26:26 2017 UTC
# Line 36  See LICENSE.TXT for the license. Line 36  See LICENSE.TXT for the license.
36  #include "util.h"  #include "util.h"
37  #include "pkt.h"  #include "pkt.h"
38    
 //#define READAMOUNT 60000  
 // 60000 -> 65536 へ拡張。SSH2ではwindow制御を行うため、SSH2のwindow sizeと  
 // 合わせておく必要がある。(2004.10.17 yutaka)  
 //#define READAMOUNT 65536  
 // 65536 -> 131072 へ拡張。(2007.10.29 maya)  
39  #define READAMOUNT CHAN_SES_WINDOW_DEFAULT  #define READAMOUNT CHAN_SES_WINDOW_DEFAULT
40    
41  void PKT_init(PTInstVar pvar)  void PKT_init(PTInstVar pvar)
# Line 67  static int recv_data(PTInstVar pvar, uns Line 62  static int recv_data(PTInstVar pvar, uns
62                  pvar->pkt_state.datastart = 0;                  pvar->pkt_state.datastart = 0;
63          }          }
64    
65          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen, up_to_amount);
                         up_to_amount);  
66    
67          _ASSERT(pvar->pkt_state.buf != NULL);          _ASSERT(pvar->pkt_state.buf != NULL);
68    
69          amount_read = (pvar->Precv) (pvar->socket,          amount_read = (pvar->Precv) (pvar->socket,
70                                       pvar->pkt_state.buf +                                       pvar->pkt_state.buf + pvar->pkt_state.datalen,
                                      pvar->pkt_state.datalen,  
71                                       up_to_amount - pvar->pkt_state.datalen,                                       up_to_amount - pvar->pkt_state.datalen,
72                                       0);                                       0);
73    
74          if (amount_read > 0) {          if (amount_read > 0) {
75                  /* Update seen_newline if necessary */                  /* Update seen_newline if necessary */
76                  if (!pvar->pkt_state.seen_server_ID                  if (!pvar->pkt_state.seen_server_ID && !pvar->pkt_state.seen_newline) {
                  && !pvar->pkt_state.seen_newline) {  
77                          int i;                          int i;
78    
79                          for (i = 0; i < amount_read; i++) {                          for (i = 0; i < amount_read; i++) {
80                                  if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] ==                                  if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] == '\n') {
                                     '\n') {  
81                                          pvar->pkt_state.seen_newline = 1;                                          pvar->pkt_state.seen_newline = 1;
82                                  }                                  }
83                          }                          }
84                  }                  }
   
85                  pvar->pkt_state.datalen += amount_read;                  pvar->pkt_state.datalen += amount_read;
86          }          }
87    
88          return amount_read;          return amount_read;
89  }  }
90    
   
91  // 改行コードが出てくるまで読む  // 改行コードが出てくるまで読む
92  static int recv_line_data(PTInstVar pvar)  static int recv_line_data(PTInstVar pvar)
93  {  {
# Line 115  static int recv_line_data(PTInstVar pvar Line 104  static int recv_line_data(PTInstVar pvar
104                  pvar->pkt_state.datastart = 0;                  pvar->pkt_state.datastart = 0;
105          }          }
106    
107          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen,          buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen, up_to_amount);
                         up_to_amount);  
108    
109          for (i = 0 ; i < (int)up_to_amount ; i++) {          for (i = 0 ; i < (int)up_to_amount ; i++) {
110                  amount_read = (pvar->Precv) (pvar->socket,                  amount_read = (pvar->Precv) (pvar->socket, &buf[i], 1, 0);
                                              &buf[i], 1, 0);  
111                  if (amount_read != 1) {                  if (amount_read != 1) {
112                          return 0; // error                          return 0; // error
113                  }                  }
# Line 140  static int recv_line_data(PTInstVar pvar Line 127  static int recv_line_data(PTInstVar pvar
127          return amount_read;          return amount_read;
128  }  }
129    
   
130  /* This function does two things:  /* This function does two things:
131     -- 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
132     -- copies any available decrypted session data into the application buffer     -- copies any available decrypted session data into the application buffer
# Line 158  int PKT_recv(PTInstVar pvar, char *buf, Line 144  int PKT_recv(PTInstVar pvar, char *buf,
144                          amount_in_buf += grabbed;                          amount_in_buf += grabbed;
145                          buf += grabbed;                          buf += grabbed;
146                          buflen -= grabbed;                          buflen -= grabbed;
147                    }
148                  } else if (!pvar->pkt_state.seen_server_ID &&                  else if (!pvar->pkt_state.seen_server_ID && (pvar->pkt_state.seen_newline || pvar->pkt_state.datalen >= 255)) {
149                             (pvar->pkt_state.seen_newline                          /*
150                              || pvar->pkt_state.datalen >= 255)) {                           * We're looking for the initial ID string and either we've seen the
151                          /* We're looking for the initial ID string and either we've seen the                           * terminating newline, or we've exceeded the limit at which we should see a newline.
152                             terminating newline, or we've exceeded the limit at which we should see                           */
                            a newline. */  
153                          unsigned int i;                          unsigned int i;
154    
155                          for (i = 0;                          for (i = 0; pvar->pkt_state.buf[i] != '\n' && i < pvar->pkt_state.datalen; i++) {
                              pvar->pkt_state.buf[i] != '\n'  
                              && i < pvar->pkt_state.datalen; i++) {  
156                          }                          }
157                          if (pvar->pkt_state.buf[i] == '\n') {                          if (pvar->pkt_state.buf[i] == '\n') {
158                                  i++;                                  i++;
# Line 179  int PKT_recv(PTInstVar pvar, char *buf, Line 162  int PKT_recv(PTInstVar pvar, char *buf,
162                          if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {                          if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {
163                                  pvar->pkt_state.seen_server_ID = 1;                                  pvar->pkt_state.seen_server_ID = 1;
164    
165                                  if (SSHv1(pvar)) {                                  if (SSHv2(pvar)) {
   
                                 } else { // for SSH2(yutaka)  
166                                          // send Key Exchange Init                                          // send Key Exchange Init
167                                          SSH2_send_kexinit(pvar);                                          SSH2_send_kexinit(pvar);
168                                  }                                  }
   
169                          } else {                          } else {
170                                  // reset flag to re-read server ID (2008.1.24 yutaka)                                  // reset flag to re-read server ID (2008.1.24 yutaka)
171                                  pvar->pkt_state.seen_newline = 0;                                  pvar->pkt_state.seen_newline = 0;
   
172                          }                          }
173    
174                          pvar->pkt_state.datastart += i;                          pvar->pkt_state.datastart += i;
175                          pvar->pkt_state.datalen -= i;                          pvar->pkt_state.datalen -= i;
176                    }
177                  } else if (pvar->pkt_state.seen_server_ID                  else if (pvar->pkt_state.seen_server_ID && pvar->pkt_state.datalen >= (unsigned int) SSH_get_min_packet_size(pvar)) {
178                             && pvar->pkt_state.datalen >=                          char *data = pvar->pkt_state.buf + pvar->pkt_state.datastart;
                            (unsigned int) SSH_get_min_packet_size(pvar)) {  
                         char *data =  
                                 pvar->pkt_state.buf + pvar->pkt_state.datastart;  
179                          uint32 padding;                          uint32 padding;
180                          uint32 pktsize;                          uint32 pktsize;
181                          uint32 total_packet_size;                          uint32 total_packet_size;
182                            struct Mac *mac = &pvar->ssh2_keys[MODE_IN].mac;
183                            int etm;
184    
185                          //debug_print(10, data, pvar->pkt_state.datalen);                          etm = mac && mac->enabled && mac->etm;
186    
187                          // 暗号化パケットの一部を復号化する。                          /*
188                          if (!pvar->pkt_state.predecrypted_packet) {                           * 通常の MAC 方式 (E&M: Encrypt & MAC) ではパケット長部分も暗号化されているため、
189                             * 先頭の 1 ブロックを復号する。MAC 方式が EtM (Encrypt then MAC) の時は
190                             * パケット長部分は暗号化されていないので復号は必要無い。
191                             */
192                            if (!pvar->pkt_state.predecrypted_packet && !etm) {
193                                  SSH_predecrpyt_packet(pvar, data);                                  SSH_predecrpyt_packet(pvar, data);
194                                  pvar->pkt_state.predecrypted_packet = TRUE;                                  pvar->pkt_state.predecrypted_packet = TRUE;
195                          }                          }
# Line 218  int PKT_recv(PTInstVar pvar, char *buf, Line 200  int PKT_recv(PTInstVar pvar, char *buf,
200                                  padding = 8 - (realpktsize % 8);                                  padding = 8 - (realpktsize % 8);
201                                  pktsize = realpktsize + padding;                                  pktsize = realpktsize + padding;
202                          } else {                          } else {
203                                  // SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。                                  // SSH2 ではパケットの先頭に uint32 (4バイト) のパケット長が来る
204                                  pktsize = get_uint32_MSBfirst(data);                                  pktsize = get_uint32_MSBfirst(data);
205                                  padding = (unsigned char) data[4];  
206                                    // 続く 1 バイトは padding の長さ
207                                    if (etm) {
208                                            // EtM では padding length 以降は暗号化されている。
209                                            // この時点ではまだ復号していないので padding length が分からない。
210                                            // 仮に 0 を入れて置く。
211                                            padding = 0;
212                                    }
213                                    else {
214                                            // E&M では復号済み
215                                            padding = (unsigned char) data[4];
216                                    }
217                          }                          }
218    
219                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。
220                          // +4は、SSHペイロードのサイズを格納している部分(int型)。                          // +4は、SSHペイロードのサイズを格納している部分(int型)。
221                          total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);                          total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);
222    
223                          if (total_packet_size <= pvar->pkt_state.datalen) {                          if (total_packet_size <= pvar->pkt_state.datalen) {
224                                  /* the data must be 4 byte aligned. */                                  // 受信済みデータが十分有る場合はパケットの実処理を行う
225                                  SSH_handle_packet(pvar, data, pktsize, padding);                                  if (SSHv1(pvar)) {
226                                  pvar->pkt_state.predecrypted_packet = FALSE;                                          // SSH1 は EtM 非対応
227                                            SSH1_handle_packet(pvar, data, pktsize, padding);
228                                    }
229                                    else {
230                                            SSH2_handle_packet(pvar, data, pktsize, padding, etm);
231                                    }
232    
233                                    pvar->pkt_state.predecrypted_packet = FALSE;
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 > PACKET_MAX_SIZE) {                          } else if (total_packet_size > PACKET_MAX_SIZE) {
238                                  // 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, TRUE);                                  notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
243                          } else {                          } else {
244                                  int amount_read =                                  int amount_read = recv_data(pvar, max(total_packet_size, READAMOUNT));
                                         recv_data(pvar, max(total_packet_size, READAMOUNT));  
245    
246                                  if (amount_read == SOCKET_ERROR) {                                  if (amount_read == SOCKET_ERROR) {
247                                          if (amount_in_buf == 0) {                                          if (amount_in_buf == 0) {
# Line 257  int PKT_recv(PTInstVar pvar, char *buf, Line 255  int PKT_recv(PTInstVar pvar, char *buf,
255                                          }                                          }
256                                  }                                  }
257                          }                          }
   
   
258                  } else {                  } else {
259                          // パケットの受信(最大60KB)                          // パケットの受信
260                          int amount_read;                          int amount_read;
261    
262                          if (pvar->pkt_state.seen_server_ID == 0) {                          amount_read = recv_data(pvar, READAMOUNT);
                                 //amount_read = recv_line_data(pvar);  
                                 amount_read = recv_data(pvar, READAMOUNT);  
   
                         } else {  
                                 amount_read = recv_data(pvar, READAMOUNT);  
   
                         }  
263    
264                          if (amount_read == SOCKET_ERROR) {                          if (amount_read == SOCKET_ERROR) {
265                                  if (amount_in_buf == 0) {                                  if (amount_in_buf == 0) {
# Line 289  int PKT_recv(PTInstVar pvar, char *buf, Line 278  int PKT_recv(PTInstVar pvar, char *buf,
278          }          }
279    
280          if (SSH_is_any_payload(pvar)) {          if (SSH_is_any_payload(pvar)) {
281                  PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,                  PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY, pvar->socket, MAKELPARAM(FD_READ, 0));
                             pvar->socket, MAKELPARAM(FD_READ, 0));  
282          }          }
283    
284          return amount_in_buf;          return amount_in_buf;

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

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