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;
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
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);
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 */
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
/* 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. */
/* 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));
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),
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;
******************************************************************************/
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
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;
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 */
/* 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"));
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;
}
/* 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),
{
/* 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) {
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;
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
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"));
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 ||
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,
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),
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"));
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;
}
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,