[BACK]Return to packet.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/packet.c between version 1.102 and 1.102.2.2

version 1.102, 2002/12/10 19:47:14 version 1.102.2.2, 2004/03/04 18:18:16
Line 39 
Line 39 
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
   #include <sys/queue.h>
   
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "buffer.h"  #include "buffer.h"
 #include "packet.h"  #include "packet.h"
Line 106 
Line 108 
 static int packet_compression = 0;  static int packet_compression = 0;
   
 /* default maximum packet size */  /* default maximum packet size */
 int max_packet_size = 32768;  u_int max_packet_size = 32768;
   
 /* Flag indicating whether this module has been initialized. */  /* Flag indicating whether this module has been initialized. */
 static int initialized = 0;  static int initialized = 0;
Line 116 
Line 118 
   
 /* Session key information for Encryption and MAC */  /* Session key information for Encryption and MAC */
 Newkeys *newkeys[MODE_MAX];  Newkeys *newkeys[MODE_MAX];
 static u_int32_t read_seqnr = 0;  static struct packet_state {
 static u_int32_t send_seqnr = 0;          u_int32_t seqnr;
           u_int32_t packets;
           u_int64_t blocks;
   } p_read, p_send;
   
   static u_int64_t max_blocks_in, max_blocks_out;
   static u_int32_t rekey_limit;
   
 /* Session key for protocol v1 */  /* Session key for protocol v1 */
 static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];  static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
 static u_int ssh1_keylen;  static u_int ssh1_keylen;
Line 126 
Line 134 
 /* roundup current message to extra_pad bytes */  /* roundup current message to extra_pad bytes */
 static u_char extra_pad = 0;  static u_char extra_pad = 0;
   
   struct packet {
           TAILQ_ENTRY(packet) next;
           u_char type;
           Buffer payload;
   };
   TAILQ_HEAD(, packet) outgoing;
   
 /*  /*
  * Sets the descriptors used for communication.  Disables encryption until   * Sets the descriptors used for communication.  Disables encryption until
  * packet_set_encryption_key is called.   * packet_set_encryption_key is called.
Line 148 
Line 163 
                 buffer_init(&output);                  buffer_init(&output);
                 buffer_init(&outgoing_packet);                  buffer_init(&outgoing_packet);
                 buffer_init(&incoming_packet);                  buffer_init(&incoming_packet);
                   TAILQ_INIT(&outgoing);
         }          }
         /* Kludge: arrange the close function to be called from fatal(). */  
         fatal_add_cleanup((void (*) (void *)) packet_close, NULL);  
 }  }
   
 /* Returns 1 if remote host is connected via socket, 0 if not. */  /* Returns 1 if remote host is connected via socket, 0 if not. */
Line 249 
Line 263 
         cipher_set_keyiv(cc, dat);          cipher_set_keyiv(cc, dat);
 }  }
 int  int
 packet_get_ssh1_cipher()  packet_get_ssh1_cipher(void)
 {  {
         return (cipher_get_number(receive_context.cipher));          return (cipher_get_number(receive_context.cipher));
 }  }
   
   void
 u_int32_t  packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets)
 packet_get_seqnr(int mode)  
 {  {
         return (mode == MODE_IN ? read_seqnr : send_seqnr);          struct packet_state *state;
   
           state = (mode == MODE_IN) ? &p_read : &p_send;
           *seqnr = state->seqnr;
           *blocks = state->blocks;
           *packets = state->packets;
 }  }
   
 void  void
 packet_set_seqnr(int mode, u_int32_t seqnr)  packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets)
 {  {
         if (mode == MODE_IN)          struct packet_state *state;
                 read_seqnr = seqnr;  
         else if (mode == MODE_OUT)          state = (mode == MODE_IN) ? &p_read : &p_send;
                 send_seqnr = seqnr;          state->seqnr = seqnr;
         else          state->blocks = blocks;
                 fatal("packet_set_seqnr: bad mode %d", mode);          state->packets = packets;
 }  }
   
 /* returns 1 if connection is via ipv4 */  /* returns 1 if connection is via ipv4 */
Line 557 
Line 575 
         Mac *mac;          Mac *mac;
         Comp *comp;          Comp *comp;
         CipherContext *cc;          CipherContext *cc;
           u_int64_t *max_blocks;
         int encrypt;          int encrypt;
   
         debug2("set_newkeys: mode %d", mode);          debug2("set_newkeys: mode %d", mode);
Line 564 
Line 583 
         if (mode == MODE_OUT) {          if (mode == MODE_OUT) {
                 cc = &send_context;                  cc = &send_context;
                 encrypt = CIPHER_ENCRYPT;                  encrypt = CIPHER_ENCRYPT;
                   p_send.packets = p_send.blocks = 0;
                   max_blocks = &max_blocks_out;
         } else {          } else {
                 cc = &receive_context;                  cc = &receive_context;
                 encrypt = CIPHER_DECRYPT;                  encrypt = CIPHER_DECRYPT;
                   p_read.packets = p_read.blocks = 0;
                   max_blocks = &max_blocks_in;
         }          }
         if (newkeys[mode] != NULL) {          if (newkeys[mode] != NULL) {
                 debug("set_newkeys: rekeying");                  debug("set_newkeys: rekeying");
Line 605 
Line 628 
                         buffer_compress_init_recv();                          buffer_compress_init_recv();
                 comp->enabled = 1;                  comp->enabled = 1;
         }          }
           /*
            * The 2^(blocksize*2) limit is too expensive for 3DES,
            * blowfish, etc, so enforce a 1GB limit for small blocksizes.
            */
           if (enc->block_size >= 16)
                   *max_blocks = (u_int64_t)1 << (enc->block_size*2);
           else
                   *max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
           if (rekey_limit)
                   *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
 }  }
   
 /*  /*
  * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)   * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
  */   */
 static void  static void
 packet_send2(void)  packet_send2_wrapped(void)
 {  {
         u_char type, *cp, *macbuf = NULL;          u_char type, *cp, *macbuf = NULL;
         u_char padlen, pad;          u_char padlen, pad;
Line 693 
Line 726 
   
         /* compute MAC over seqnr and packet(length fields, payload, padding) */          /* compute MAC over seqnr and packet(length fields, payload, padding) */
         if (mac && mac->enabled) {          if (mac && mac->enabled) {
                 macbuf = mac_compute(mac, send_seqnr,                  macbuf = mac_compute(mac, p_send.seqnr,
                     buffer_ptr(&outgoing_packet),                      buffer_ptr(&outgoing_packet),
                     buffer_len(&outgoing_packet));                      buffer_len(&outgoing_packet));
                 DBG(debug("done calc MAC out #%d", send_seqnr));                  DBG(debug("done calc MAC out #%d", p_send.seqnr));
         }          }
         /* encrypt packet and append to output buffer. */          /* encrypt packet and append to output buffer. */
         cp = buffer_append_space(&output, buffer_len(&outgoing_packet));          cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
Line 710 
Line 743 
         buffer_dump(&output);          buffer_dump(&output);
 #endif  #endif
         /* increment sequence number for outgoing packets */          /* increment sequence number for outgoing packets */
         if (++send_seqnr == 0)          if (++p_send.seqnr == 0)
                 log("outgoing seqnr wraps around");                  logit("outgoing seqnr wraps around");
           if (++p_send.packets == 0)
                   if (!(datafellows & SSH_BUG_NOREKEY))
                           fatal("XXX too many packets with same key");
           p_send.blocks += (packet_length + 4) / block_size;
         buffer_clear(&outgoing_packet);          buffer_clear(&outgoing_packet);
   
         if (type == SSH2_MSG_NEWKEYS)          if (type == SSH2_MSG_NEWKEYS)
                 set_newkeys(MODE_OUT);                  set_newkeys(MODE_OUT);
 }  }
   
   static void
   packet_send2(void)
   {
           static int rekeying = 0;
           struct packet *p;
           u_char type, *cp;
   
           cp = buffer_ptr(&outgoing_packet);
           type = cp[5];
   
           /* during rekeying we can only send key exchange messages */
           if (rekeying) {
                   if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
                       (type <= SSH2_MSG_TRANSPORT_MAX))) {
                           debug("enqueue packet: %u", type);
                           p = xmalloc(sizeof(*p));
                           p->type = type;
                           memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
                           buffer_init(&outgoing_packet);
                           TAILQ_INSERT_TAIL(&outgoing, p, next);
                           return;
                   }
           }
   
           /* rekeying starts with sending KEXINIT */
           if (type == SSH2_MSG_KEXINIT)
                   rekeying = 1;
   
           packet_send2_wrapped();
   
           /* after a NEWKEYS message we can send the complete queue */
           if (type == SSH2_MSG_NEWKEYS) {
                   rekeying = 0;
                   while ((p = TAILQ_FIRST(&outgoing))) {
                           type = p->type;
                           debug("dequeue packet: %u", type);
                           buffer_free(&outgoing_packet);
                           memcpy(&outgoing_packet, &p->payload,
                               sizeof(Buffer));
                           TAILQ_REMOVE(&outgoing, p, next);
                           xfree(p);
                           packet_send2_wrapped();
                   }
           }
   }
   
 void  void
 packet_send(void)  packet_send(void)
 {  {
Line 779 
Line 862 
                 /* Read data from the socket. */                  /* Read data from the socket. */
                 len = read(connection_in, buf, sizeof(buf));                  len = read(connection_in, buf, sizeof(buf));
                 if (len == 0) {                  if (len == 0) {
                         log("Connection closed by %.200s", get_remote_ipaddr());                          logit("Connection closed by %.200s", get_remote_ipaddr());
                         fatal_cleanup();                          cleanup_exit(255);
                 }                  }
                 if (len < 0)                  if (len < 0)
                         fatal("Read from socket failed: %.100s", strerror(errno));                          fatal("Read from socket failed: %.100s", strerror(errno));
Line 930 
Line 1013 
                 cp = buffer_ptr(&incoming_packet);                  cp = buffer_ptr(&incoming_packet);
                 packet_length = GET_32BIT(cp);                  packet_length = GET_32BIT(cp);
                 if (packet_length < 1 + 4 || packet_length > 256 * 1024) {                  if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
   #ifdef PACKET_DEBUG
                         buffer_dump(&incoming_packet);                          buffer_dump(&incoming_packet);
   #endif
                         packet_disconnect("Bad packet length %u.", packet_length);                          packet_disconnect("Bad packet length %u.", packet_length);
                 }                  }
                 DBG(debug("input: packet len %u", packet_length+4));                  DBG(debug("input: packet len %u", packet_length+4));
Line 961 
Line 1046 
          * increment sequence number for incoming packet           * increment sequence number for incoming packet
          */           */
         if (mac && mac->enabled) {          if (mac && mac->enabled) {
                 macbuf = mac_compute(mac, read_seqnr,                  macbuf = mac_compute(mac, p_read.seqnr,
                     buffer_ptr(&incoming_packet),                      buffer_ptr(&incoming_packet),
                     buffer_len(&incoming_packet));                      buffer_len(&incoming_packet));
                 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)                  if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
                         packet_disconnect("Corrupted MAC on input.");                          packet_disconnect("Corrupted MAC on input.");
                 DBG(debug("MAC #%d ok", read_seqnr));                  DBG(debug("MAC #%d ok", p_read.seqnr));
                 buffer_consume(&input, mac->mac_len);                  buffer_consume(&input, mac->mac_len);
         }          }
         if (seqnr_p != NULL)          if (seqnr_p != NULL)
                 *seqnr_p = read_seqnr;                  *seqnr_p = p_read.seqnr;
         if (++read_seqnr == 0)          if (++p_read.seqnr == 0)
                 log("incoming seqnr wraps around");                  logit("incoming seqnr wraps around");
           if (++p_read.packets == 0)
                   if (!(datafellows & SSH_BUG_NOREKEY))
                           fatal("XXX too many packets with same key");
           p_read.blocks += (packet_length + 4) / block_size;
   
         /* get padlen */          /* get padlen */
         cp = buffer_ptr(&incoming_packet);          cp = buffer_ptr(&incoming_packet);
Line 1037 
Line 1126 
                         case SSH2_MSG_DISCONNECT:                          case SSH2_MSG_DISCONNECT:
                                 reason = packet_get_int();                                  reason = packet_get_int();
                                 msg = packet_get_string(NULL);                                  msg = packet_get_string(NULL);
                                 log("Received disconnect from %s: %u: %.400s",                                  logit("Received disconnect from %s: %u: %.400s",
                                     get_remote_ipaddr(), reason, msg);                                      get_remote_ipaddr(), reason, msg);
                                 xfree(msg);                                  xfree(msg);
                                 fatal_cleanup();                                  cleanup_exit(255);
                                 break;                                  break;
                         case SSH2_MSG_UNIMPLEMENTED:                          case SSH2_MSG_UNIMPLEMENTED:
                                 seqnr = packet_get_int();                                  seqnr = packet_get_int();
Line 1063 
Line 1152 
                                 break;                                  break;
                         case SSH_MSG_DISCONNECT:                          case SSH_MSG_DISCONNECT:
                                 msg = packet_get_string(NULL);                                  msg = packet_get_string(NULL);
                                 log("Received disconnect from %s: %.400s",                                  logit("Received disconnect from %s: %.400s",
                                     get_remote_ipaddr(), msg);                                      get_remote_ipaddr(), msg);
                                 fatal_cleanup();                                  cleanup_exit(255);
                                 xfree(msg);                                  xfree(msg);
                                 break;                                  break;
                         default:                          default:
Line 1222 
Line 1311 
         va_end(args);          va_end(args);
   
         /* Display the error locally */          /* Display the error locally */
         log("Disconnecting: %.100s", buf);          logit("Disconnecting: %.100s", buf);
   
         /* Send the disconnect message to the other side, and wait for it to get sent. */          /* Send the disconnect message to the other side, and wait for it to get sent. */
         if (compat20) {          if (compat20) {
Line 1242 
Line 1331 
   
         /* Close the connection. */          /* Close the connection. */
         packet_close();          packet_close();
           cleanup_exit(255);
         fatal_cleanup();  
 }  }
   
 /* Checks if there is any buffered output, and tries to write some of the output. */  /* Checks if there is any buffered output, and tries to write some of the output. */
Line 1353 
Line 1441 
         return interactive_mode;          return interactive_mode;
 }  }
   
 int  u_int
 packet_set_maxsize(int s)  packet_set_maxsize(u_int s)
 {  {
         static int called = 0;          static int called = 0;
   
         if (called) {          if (called) {
                 log("packet_set_maxsize: called twice: old %d new %d",                  logit("packet_set_maxsize: called twice: old %d new %d",
                     max_packet_size, s);                      max_packet_size, s);
                 return -1;                  return -1;
         }          }
         if (s < 4 * 1024 || s > 1024 * 1024) {          if (s < 4 * 1024 || s > 1024 * 1024) {
                 log("packet_set_maxsize: bad size %d", s);                  logit("packet_set_maxsize: bad size %d", s);
                 return -1;                  return -1;
         }          }
         called = 1;          called = 1;
Line 1405 
Line 1493 
                 packet_put_char(rand & 0xff);                  packet_put_char(rand & 0xff);
                 rand >>= 8;                  rand >>= 8;
         }          }
   }
   
   #define MAX_PACKETS     (1<<31)
   int
   packet_need_rekeying(void)
   {
           if (datafellows & SSH_BUG_NOREKEY)
                   return 0;
           return
               (p_send.packets > MAX_PACKETS) ||
               (p_read.packets > MAX_PACKETS) ||
               (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
               (max_blocks_in  && (p_read.blocks > max_blocks_in));
   }
   
   void
   packet_set_rekey_limit(u_int32_t bytes)
   {
           rekey_limit = bytes;
 }  }

Legend:
Removed from v.1.102  
changed lines
  Added in v.1.102.2.2