Integer type name change.
[silc.git] / lib / silccore / silcpacket.c
index f21ae66a900a9d19f2c6be8b6761d53a42cc8861..7f72922b5d6c4aac3de4ecbde37d0dfaa933c16e 100644 (file)
@@ -56,7 +56,8 @@ int silc_packet_send(SilcSocketConnection sock, bool force_send)
     ret = silc_socket_write(sock);
 
     if (ret == -1) {
-      SILC_LOG_ERROR(("Error sending packet, dropped"));
+      SILC_LOG_ERROR(("Error sending packet, dropped: %s", 
+                      strerror(errno)));
     }
     if (ret != -2)
       return ret;
@@ -76,11 +77,11 @@ int silc_packet_send(SilcSocketConnection sock, bool force_send)
    other process of HMAC computing and encryption is needed this function
    cannot be used. */
 
-void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, uint32 sequence,
-                        SilcBuffer buffer, uint32 len)
+void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, SilcUInt32 sequence,
+                        SilcBuffer buffer, SilcUInt32 len)
 {
   unsigned char mac[32];
-  uint32 mac_len;
+  SilcUInt32 mac_len;
 
   /* Compute HMAC. This assumes that HMAC is created from the entire
      data area thus this uses the length found in buffer, not the length
@@ -89,14 +90,8 @@ void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, uint32 sequence,
     unsigned char psn[4];
 
     silc_hmac_init(hmac);
-
-    /* XXX Backwards support for old MAC computation.
-       XXX Remove in 0.7.x */
-    if (!silc_hmac_get_b(hmac)) {
-      SILC_PUT32_MSB(sequence, psn);
-      silc_hmac_update(hmac, psn, 4);
-    }
-
+    SILC_PUT32_MSB(sequence, psn);
+    silc_hmac_update(hmac, psn, 4);
     silc_hmac_update(hmac, buffer->data, buffer->len);
     silc_hmac_final(hmac, mac, &mac_len);
     silc_buffer_put_tail(buffer, mac, mac_len);
@@ -107,13 +102,7 @@ void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, uint32 sequence,
   if (cipher) {
     SILC_LOG_DEBUG(("Encrypting packet, cipher %s, len %d", 
                    cipher->cipher->name, len));
-    /* XXX Backwards support for 0.5.x 
-       XXX Remove in 0.7.x */
-    if (hmac && silc_hmac_get_b(hmac))
-      silc_cipher_encrypt(cipher, buffer->data + 2, buffer->data + 2, 
-                         len - 1, cipher->iv);
-    else
-      silc_cipher_encrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
+    silc_cipher_encrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
   }
 
   /* Pull the HMAC into the visible data area in the buffer */
@@ -150,8 +139,10 @@ void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, uint32 sequence,
       2 bytes     Payload length
       1 byte      Flags
       1 byte      Packet type
-      2 bytes     Source ID Length
-      2 bytes     Destination ID Length
+      1 byte      Padding length
+      1 byte      RESERVED
+      1 bytes     Source ID Length
+      1 bytes     Destination ID Length
       1 byte      Source ID Type
       n bytes     Source ID
       1 byte      Destination ID Type
@@ -185,11 +176,10 @@ void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
   /* Calculate the length of the padding. The padding is calculated from
      the data that will be encrypted. */
   if (!ctx->padlen) {
-    ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
-    /* XXX backwards support for 0.5.x
-       XXX remove in 0.7.x */
-    if (cipher->back)
-      ctx->padlen = SILC_PACKET_PADLEN2(ctx->truelen, block_len);
+    if (ctx->long_pad)
+      ctx->padlen = SILC_PACKET_PADLEN_MAX(ctx->truelen);
+    else
+      ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
   }
 
   /* Put the start of the data section to the right place. */
@@ -198,7 +188,8 @@ void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
 
   /* Get random padding */
 #if 1
-  for (i = 0; i < ctx->padlen; i++) tmppad[i] = silc_rng_global_get_byte();
+  for (i = 0; i < ctx->padlen; i++) tmppad[i] = 
+                                     silc_rng_global_get_byte_fast();
 #else
   /* XXX: For testing - to be removed */
   memset(tmppad, 65, sizeof(tmppad));
@@ -210,8 +201,10 @@ void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
                     SILC_STR_UI_SHORT(ctx->truelen),
                     SILC_STR_UI_CHAR(ctx->flags),
                     SILC_STR_UI_CHAR(ctx->type),
-                    SILC_STR_UI_SHORT(ctx->src_id_len),
-                    SILC_STR_UI_SHORT(ctx->dst_id_len),
+                    SILC_STR_UI_CHAR(ctx->padlen),
+                    SILC_STR_UI_CHAR(0),
+                    SILC_STR_UI_CHAR(ctx->src_id_len),
+                    SILC_STR_UI_CHAR(ctx->dst_id_len),
                     SILC_STR_UI_CHAR(ctx->src_id_type),
                     SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
                     SILC_STR_UI_CHAR(ctx->dst_id_type),
@@ -231,9 +224,9 @@ void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
    outgoing buffer in SilcSocketConnection object. */
 
 void silc_packet_send_prepare(SilcSocketConnection sock,
-                             uint32 header_len,
-                             uint32 padlen,
-                             uint32 data_len)
+                             SilcUInt32 header_len,
+                             SilcUInt32 padlen,
+                             SilcUInt32 data_len)
 {
   int totlen, oldlen;
 
@@ -291,7 +284,7 @@ void silc_packet_send_prepare(SilcSocketConnection sock,
 ******************************************************************************/
 
 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, 
-                              uint32 sequence, SilcBuffer buffer, 
+                              SilcUInt32 sequence, SilcBuffer buffer, 
                               bool normal);
 
 /* Receives packet from network and reads the data into connection's
@@ -331,68 +324,63 @@ int silc_packet_receive(SilcSocketConnection sock)
    SilcPacketParserContext will indicate also whether the received
    packet was normal or special packet. */
 
-void silc_packet_receive_process(SilcSocketConnection sock,
+bool silc_packet_receive_process(SilcSocketConnection sock,
                                 bool local_is_router,
                                 SilcCipher cipher, SilcHmac hmac,
-                                uint32 sequence,
+                                SilcUInt32 sequence,
                                 SilcPacketParserCallback parser,
                                 void *parser_context)
 {
   SilcPacketParserContext *parse_ctx;
   int packetlen, paddedlen, mac_len = 0;
-  int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
+  bool cont = TRUE;
+
+  /* Do not process for disconnected connection */
+  if (SILC_IS_DISCONNECTED(sock))
+    return TRUE;
 
   if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
-    return;
+    return TRUE;
 
   if (hmac)
     mac_len = silc_hmac_len(hmac);
 
   /* Parse the packets from the data */
-  while (sock->inbuf->len > 0) {
+  while (sock->inbuf->len > 0 && cont) {
 
-    /* Decrypt first 16 bytes of the packet */
-    if (!SILC_IS_INBUF_PENDING(sock) && cipher) {
-      /* XXX backwards support for 0.5.x
-        XXX remove in 0.7.x */
-      if (cipher->back)
-       silc_cipher_decrypt(cipher, sock->inbuf->data + 2, 
-                           sock->inbuf->data + 2, 
-                           SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
-      else
-       silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data, 
-                           SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
+    if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
+      SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
+      return TRUE;
     }
 
+    /* Decrypt first 16 bytes of the packet */
+    if (!SILC_IS_INBUF_PENDING(sock) && cipher)
+      silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data, 
+                         SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
+
     /* Get packet lenght and full packet length with padding */
-    SILC_PACKET_LENGTH(sock->inbuf, packetlen);
-    /* XXX backwards support for 0.5.x
-       XXX remove in 0.7.x */
-    if (cipher && cipher->back) {
-      paddedlen = packetlen + SILC_PACKET_PADLEN2(packetlen, block_len);
-      paddedlen += 2;
-    } else {
-      paddedlen = packetlen + SILC_PACKET_PADLEN(packetlen, block_len);
-    }
+    SILC_PACKET_LENGTH(sock->inbuf, packetlen, paddedlen);
 
     /* Sanity checks */
     if (packetlen < SILC_PACKET_MIN_LEN) {
       SILC_LOG_DEBUG(("Received invalid packet, dropped"));
       silc_buffer_clear(sock->inbuf);
-      return;
+      return FALSE;
     }
 
     if (sock->inbuf->len < paddedlen + mac_len) {
       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
                      "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
       SILC_SET_INBUF_PENDING(sock);
-      return;
+      return TRUE;
     }
 
     SILC_UNSET_INBUF_PENDING(sock);
     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
     parse_ctx->packet = silc_packet_context_alloc();
     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
+    parse_ctx->packet->type = sock->inbuf->data[3];
+    parse_ctx->packet->padlen = sock->inbuf->data[4];
     parse_ctx->packet->sequence = sequence++;
     parse_ctx->sock = sock;
     parse_ctx->context = parser_context;
@@ -402,8 +390,9 @@ void silc_packet_receive_process(SilcSocketConnection sock,
     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
                    paddedlen + mac_len);
 
-    SILC_LOG_HEXDUMP(("Incoming packet (%d) (%d bytes decrypted), len %d", 
-                     sequence - 1, block_len, paddedlen + mac_len),
+    SILC_LOG_HEXDUMP(("Incoming packet (%d) (%dB decrypted), len %d", 
+                     sequence - 1, SILC_PACKET_MIN_HEADER_LEN, 
+                     paddedlen + mac_len),
                     sock->inbuf->data, paddedlen + mac_len);
 
     /* Check whether this is normal or special packet */
@@ -425,32 +414,43 @@ void silc_packet_receive_process(SilcSocketConnection sock,
 
     /* Decrypt rest of the packet */
     if (cipher)
-      silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
-                         parse_ctx->packet->buffer, parse_ctx->normal);
-
-    /* Call the parser */
-    if (parser)
-      (*parser)(parse_ctx, parser_context);
+      if (silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
+                             parse_ctx->packet->buffer, 
+                             parse_ctx->normal) == -1) {
+       SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s]", 
+                         sock->hostname, sock->port,
+                         (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+                          sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+                          sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+                          "Router")));
+      }
 
     /* Pull the packet from inbuf thus we'll get the next one
        in the inbuf. */
     silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
+
+    /* Call the parser */
+    cont = (*parser)(parse_ctx, parser_context);
   }
 
+  if (cont == FALSE && sock->inbuf->len > 0)
+    return TRUE;
+
   SILC_LOG_DEBUG(("Clearing inbound buffer"));
   silc_buffer_clear(sock->inbuf);
+  return TRUE;
 }
 
 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
    after packet has been totally decrypted and parsed. */
 
 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
-                                uint32 sequence)
+                                SilcUInt32 sequence)
 {
   /* Check MAC */
   if (hmac) {
     unsigned char mac[32], psn[4];
-    uint32 mac_len;
+    SilcUInt32 mac_len;
     
     SILC_LOG_DEBUG(("Verifying MAC"));
 
@@ -458,21 +458,14 @@ static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
 
     memset(mac, 0, sizeof(mac));
     silc_hmac_init(hmac);
-
-    /* XXX Backwards support for old MAC computation.
-       XXX Remove in 0.7.x */
-    if (!silc_hmac_get_b(hmac)) {
-      SILC_PUT32_MSB(sequence, psn);
-      silc_hmac_update(hmac, psn, 4);
-    }
-
+    SILC_PUT32_MSB(sequence, psn);
+    silc_hmac_update(hmac, psn, 4);
     silc_hmac_update(hmac, buffer->data, buffer->len);
     silc_hmac_final(hmac, mac, &mac_len);
 
     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
-    if (memcmp(mac, buffer->tail, mac_len)) {
+    if (memcmp(buffer->tail, mac, mac_len)) {
       SILC_LOG_ERROR(("MAC failed"));
-      assert(FALSE);
       return FALSE;
     }
     
@@ -507,15 +500,8 @@ static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
 
     /* Decrypt rest of the packet */
     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
-    /* XXX backwards support for 0.5.x
-       XXX remove in 0.7.x */
-    if (cipher->back)
-      silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
-                         buffer->len - 2, 
-                         cipher->iv);
-    else
-      silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
-                         cipher->iv);
+    silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
+                       cipher->iv);
     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
 
     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
@@ -537,7 +523,7 @@ static int silc_packet_decrypt_rest_special(SilcCipher cipher,
 {
   /* Decrypt rest of the header plus padding */
   if (cipher) {
-    uint16 truelen, len1, len2, padlen, blocklen;
+    SilcUInt16 len;
 
     /* Pull MAC from packet before decryption */
     if (hmac) {
@@ -551,45 +537,22 @@ static int silc_packet_decrypt_rest_special(SilcCipher cipher,
   
     SILC_LOG_DEBUG(("Decrypting rest of the header"));
 
-    SILC_GET16_MSB(len1, &buffer->data[4]);
-    SILC_GET16_MSB(len2, &buffer->data[6]);
-
-    blocklen = silc_cipher_get_block_len(cipher);
-    truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
-
-    /* XXX backwards support for 0.5.x
-       XXX remove in 0.7.x */
-    if (cipher->back) {
-      padlen = SILC_PACKET_PADLEN2(truelen, blocklen);
-      len1 = (truelen + padlen) - (SILC_PACKET_MIN_HEADER_LEN);
-      
-      silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
+    /* padding length + src id len + dst id len + header length - 16
+       bytes already decrypted, gives the rest of the encrypted packet */
+    len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] + 
+          (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
+          SILC_PACKET_MIN_HEADER_LEN);
 
-      if (len1 - 2 > buffer->len) {
-       SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
-                       "packet dropped"));
-       return FALSE;
-      }
-
-      silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
-                         len1 - 2, cipher->iv);
-    } else {
-      blocklen = silc_cipher_get_block_len(cipher);
-      truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
-      padlen = SILC_PACKET_PADLEN(truelen, blocklen);
-      len1 = (truelen + padlen) - SILC_PACKET_MIN_HEADER_LEN;
-      
-      silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
-
-      if (len1 > buffer->len) {
-       SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
-                       "packet dropped"));
-       return FALSE;
-      }
-      
-      silc_cipher_decrypt(cipher, buffer->data, buffer->data, len1, cipher->iv);
+    silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
+    if (len > buffer->len) {
+      SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
+                     "packet dropped"));
+      return FALSE;
     }
+    silc_cipher_decrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
+    SILC_LOG_HEXDUMP(("packet, len %d", buffer->len), 
+                    buffer->data, buffer->len);
   }
 
   return TRUE;
@@ -610,7 +573,7 @@ static int silc_packet_decrypt_rest_special(SilcCipher cipher,
    is special and requires special procesing. */
 
 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
-                              uint32 sequence, SilcBuffer buffer, 
+                              SilcUInt32 sequence, SilcBuffer buffer, 
                               bool normal)
 {
   /* If the packet type is not any special type lets decrypt rest
@@ -648,8 +611,8 @@ static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
 {
   SilcBuffer buffer = ctx->buffer;
+  SilcUInt8 tmp;
   int len, ret;
-  int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
 
   SILC_LOG_DEBUG(("Parsing incoming packet"));
 
@@ -664,11 +627,13 @@ SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
                             SILC_STR_UI_SHORT(&ctx->truelen),
                             SILC_STR_UI_CHAR(&ctx->flags),
                             SILC_STR_UI_CHAR(&ctx->type),
-                            SILC_STR_UI_SHORT(&ctx->src_id_len),
-                            SILC_STR_UI_SHORT(&ctx->dst_id_len),
+                            SILC_STR_UI_CHAR(&ctx->padlen),
+                            SILC_STR_UI_CHAR(&tmp),
+                            SILC_STR_UI_CHAR(&ctx->src_id_len),
+                            SILC_STR_UI_CHAR(&ctx->dst_id_len),
                             SILC_STR_UI_CHAR(&ctx->src_id_type),
                             SILC_STR_END);
-  if (len == -1)
+  if (len == -1 || tmp != 0)
     return SILC_PACKET_NONE;
 
   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
@@ -678,9 +643,6 @@ SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
     return SILC_PACKET_NONE;
   }
 
-  /* Calculate length of padding in packet */
-  ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
-
   silc_buffer_pull(buffer, len);
   ret = silc_buffer_unformat(buffer, 
                             SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
@@ -693,15 +655,6 @@ SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
   if (ret == -1)
     return SILC_PACKET_NONE;
 
-  /* XXX backwards support for 0.5.x
-     XXX remove in 0.7.x */
-  silc_buffer_pull(buffer, 
-                  ctx->src_id_len + 1 + ctx->dst_id_len + ctx->padlen);
-  SILC_LOG_DEBUG(("**************** %d", buffer->len));
-  if (buffer->len == 2)
-    ctx->padlen += 2;
-  silc_buffer_push(buffer, ret);
-
   silc_buffer_push(buffer, len);
 
   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
@@ -726,8 +679,8 @@ SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
                                         SilcCipher cipher)
 {
   SilcBuffer buffer = ctx->buffer;
-  int len, tmplen, ret;
-  int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
+  SilcUInt8 tmp;
+  int len, ret;
 
   SILC_LOG_DEBUG(("Parsing incoming packet"));
 
@@ -742,11 +695,13 @@ SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
                             SILC_STR_UI_SHORT(&ctx->truelen),
                             SILC_STR_UI_CHAR(&ctx->flags),
                             SILC_STR_UI_CHAR(&ctx->type),
-                            SILC_STR_UI_SHORT(&ctx->src_id_len),
-                            SILC_STR_UI_SHORT(&ctx->dst_id_len),
+                            SILC_STR_UI_CHAR(&ctx->padlen),
+                            SILC_STR_UI_CHAR(&tmp),
+                            SILC_STR_UI_CHAR(&ctx->src_id_len),
+                            SILC_STR_UI_CHAR(&ctx->dst_id_len),
                             SILC_STR_UI_CHAR(&ctx->src_id_type),
                             SILC_STR_END);
-  if (len == -1) {
+  if (len == -1 || tmp != 0) {
     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
     return SILC_PACKET_NONE;
   }
@@ -758,17 +713,6 @@ SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
     return SILC_PACKET_NONE;
   }
 
-  /* Calculate length of padding in packet. As this is special packet
-     the data area is not used in the padding calculation as it won't
-     be decrypted by the caller. */
-  tmplen = SILC_PACKET_HEADER_LEN + ctx->src_id_len + ctx->dst_id_len;
-  /* XXX backwards support for 0.5.x
-     XXX remove in 0.7.x */
-  if (ctx->back)
-    ctx->padlen = SILC_PACKET_PADLEN2(tmplen, block_len);
-  else
-    ctx->padlen = SILC_PACKET_PADLEN(tmplen, block_len);
-
   silc_buffer_pull(buffer, len);
   ret = silc_buffer_unformat(buffer, 
                             SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,