updates.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /*
20  * Created: Fri Jul 25 18:52:14 1997
21  */
22 /* $Id$ */
23
24 #include "silcincludes.h"
25
26 /******************************************************************************
27
28                           Packet Sending Routines
29
30 ******************************************************************************/
31
32 /* Actually sends the packet. This flushes the connections outgoing data
33    buffer. If data is sent directly to the network this returns the bytes
34    written, if error occured this returns -1 and if the data could not
35    be written directly to the network at this time this returns -2, in
36    which case the data should be queued by the caller and sent at some
37    later time. If `force_send' is TRUE this attempts to write the data
38    directly to the network, if FALSE, this returns -2. */
39
40 int silc_packet_send(SilcSocketConnection sock, bool force_send)
41 {
42   SILC_LOG_DEBUG(("Sending packet to %s:%d [%s]", sock->hostname,
43                   sock->port,  
44                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
45                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
46                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
47                    "Router")));
48
49   /* Send now if forced to do so */
50   if (force_send == TRUE) {
51     int ret;
52
53     SILC_LOG_DEBUG(("Forcing packet send, packet sent immediately"));
54
55     /* Write to network */
56     ret = silc_socket_write(sock);
57
58     if (ret == -1) {
59       SILC_LOG_ERROR(("Error sending packet, dropped"));
60     }
61     if (ret != -2)
62       return ret;
63
64     SILC_LOG_DEBUG(("Could not force the send, packet put to queue"));
65   }  
66
67   SILC_LOG_DEBUG(("Packet in queue"));
68
69   return -2;
70 }
71
72 /* Encrypts a packet. This also creates HMAC of the packet before 
73    encryption and adds the HMAC at the end of the buffer. This assumes
74    that there is enough free space at the end of the buffer to add the
75    computed HMAC. This is the normal way of encrypting packets, if some
76    other process of HMAC computing and encryption is needed this function
77    cannot be used. */
78
79 void silc_packet_encrypt(SilcCipher cipher, SilcHmac hmac, uint32 sequence,
80                          SilcBuffer buffer, uint32 len)
81 {
82   unsigned char mac[32];
83   uint32 mac_len;
84
85   /* Compute HMAC. This assumes that HMAC is created from the entire
86      data area thus this uses the length found in buffer, not the length
87      sent as argument. */
88   if (hmac) {
89     unsigned char psn[4];
90
91     silc_hmac_init(hmac);
92
93     /* XXX Backwards support for old MAC computation.
94        XXX Remove in 0.7.x */
95     if (!silc_hmac_get_b(hmac)) {
96       SILC_PUT32_MSB(sequence, psn);
97       silc_hmac_update(hmac, psn, 4);
98     }
99
100     silc_hmac_update(hmac, buffer->data, buffer->len);
101     silc_hmac_final(hmac, mac, &mac_len);
102     silc_buffer_put_tail(buffer, mac, mac_len);
103     memset(mac, 0, sizeof(mac));
104   }
105
106   /* Encrypt the data area of the packet. */
107   if (cipher) {
108     SILC_LOG_DEBUG(("Encrypting packet, cipher %s, len %d", 
109                     cipher->cipher->name, len));
110     /* XXX Backwards support for 0.5.x 
111        XXX Remove in 0.7.x */
112     if (hmac && silc_hmac_get_b(hmac))
113       silc_cipher_encrypt(cipher, buffer->data + 2, buffer->data + 2, 
114                           len - 1, cipher->iv);
115     else
116       silc_cipher_encrypt(cipher, buffer->data, buffer->data, len, cipher->iv);
117   }
118
119   /* Pull the HMAC into the visible data area in the buffer */
120   if (hmac)
121     silc_buffer_pull_tail(buffer, mac_len);
122 }
123
124 /* Assembles a new packet to be ready for send out. The buffer sent as
125    argument must include the data to be sent and it must not be encrypted. 
126    The packet also must have enough free space so that the SILC header
127    and padding maybe added to the packet. The packet is encrypted after 
128    this function has returned.
129
130    The buffer sent as argument should be something like following:
131
132    --------------------------------------------
133    | head             | data           | tail |
134    --------------------------------------------
135    ^                  ^
136    58 bytes           x bytes
137
138    So that the SILC header and 1 - 16 bytes of padding can fit to
139    the buffer. After assembly the buffer might look like this:
140
141    --------------------------------------------
142    | data                              |      |
143    --------------------------------------------
144    ^                                   ^
145    Start of assembled packet
146
147    Packet construct is as follows:
148
149    n bytes       SILC Header
150       2 bytes     Payload length
151       1 byte      Flags
152       1 byte      Packet type
153       2 bytes     Source ID Length
154       2 bytes     Destination ID Length
155       1 byte      Source ID Type
156       n bytes     Source ID
157       1 byte      Destination ID Type
158       n bytes     Destination ID
159
160    1 - 16 bytes    Padding
161
162    n bytes        Data payload
163
164    All fields in the packet will be authenticated by MAC. The MAC is
165    not computed here, it must be computed separately before encrypting
166    the packet.
167
168 */
169
170 void silc_packet_assemble(SilcPacketContext *ctx, SilcCipher cipher)
171 {
172   unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
173   int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
174   int i;
175
176   SILC_LOG_DEBUG(("Assembling outgoing packet"));
177   
178   /* Get the true length of the packet. This is saved as payload length
179      into the packet header. This does not include the length of the
180      padding. */
181   if (!ctx->truelen)
182     ctx->truelen = ctx->buffer->len + SILC_PACKET_HEADER_LEN + 
183       ctx->src_id_len + ctx->dst_id_len;
184
185   /* Calculate the length of the padding. The padding is calculated from
186      the data that will be encrypted. */
187   if (!ctx->padlen) {
188     ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
189     /* XXX backwards support for 0.5.x
190        XXX remove in 0.7.x */
191     if (cipher->back)
192       ctx->padlen = SILC_PACKET_PADLEN2(ctx->truelen, block_len);
193   }
194
195   /* Put the start of the data section to the right place. */
196   silc_buffer_push(ctx->buffer, SILC_PACKET_HEADER_LEN + 
197                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
198
199   /* Get random padding */
200 #if 1
201   for (i = 0; i < ctx->padlen; i++) tmppad[i] = silc_rng_global_get_byte();
202 #else
203   /* XXX: For testing - to be removed */
204   memset(tmppad, 65, sizeof(tmppad));
205 #endif
206
207   /* Create the packet. This creates the SILC header and adds padding,
208      rest of the buffer remains as it is. */
209   silc_buffer_format(ctx->buffer, 
210                      SILC_STR_UI_SHORT(ctx->truelen),
211                      SILC_STR_UI_CHAR(ctx->flags),
212                      SILC_STR_UI_CHAR(ctx->type),
213                      SILC_STR_UI_SHORT(ctx->src_id_len),
214                      SILC_STR_UI_SHORT(ctx->dst_id_len),
215                      SILC_STR_UI_CHAR(ctx->src_id_type),
216                      SILC_STR_UI_XNSTRING(ctx->src_id, ctx->src_id_len),
217                      SILC_STR_UI_CHAR(ctx->dst_id_type),
218                      SILC_STR_UI_XNSTRING(ctx->dst_id, ctx->dst_id_len),
219                      SILC_STR_UI_XNSTRING(tmppad, ctx->padlen),
220                      SILC_STR_END);
221
222   SILC_LOG_HEXDUMP(("Assembled packet, len %d", ctx->buffer->len), 
223                    ctx->buffer->data, ctx->buffer->len);
224
225   SILC_LOG_DEBUG(("Outgoing packet assembled"));
226 }
227
228 /* Prepare outgoing data buffer for packet sending. This moves the data
229    area so that new packet may be added into it. If needed this allocates
230    more space to the buffer. This handles directly the connection's
231    outgoing buffer in SilcSocketConnection object. */
232
233 void silc_packet_send_prepare(SilcSocketConnection sock,
234                               uint32 header_len,
235                               uint32 padlen,
236                               uint32 data_len)
237 {
238   int totlen, oldlen;
239
240   totlen = header_len + padlen + data_len;
241
242   /* Prepare the outgoing buffer for packet sending. */
243   if (!sock->outbuf) {
244     /* Allocate new buffer. This is done only once per connection. */
245     SILC_LOG_DEBUG(("Allocating outgoing data buffer"));
246     
247     if (totlen > SILC_PACKET_DEFAULT_SIZE)
248       sock->outbuf = silc_buffer_alloc(totlen);
249     else
250       sock->outbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE);
251     silc_buffer_pull_tail(sock->outbuf, totlen);
252     silc_buffer_pull(sock->outbuf, header_len + padlen);
253   } else {
254     if (SILC_IS_OUTBUF_PENDING(sock)) {
255       /* There is some pending data in the buffer. */
256
257       /* Allocate more space if needed */
258       if ((sock->outbuf->end - sock->outbuf->tail) < 
259           (totlen + 20)) {
260         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
261         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
262                                            sock->outbuf->truelen +
263                                            (totlen * 2));
264       }
265
266       oldlen = sock->outbuf->len;
267       silc_buffer_pull_tail(sock->outbuf, totlen);
268       silc_buffer_pull(sock->outbuf, header_len + padlen + oldlen);
269     } else {
270       /* Buffer is free for use */
271       silc_buffer_clear(sock->outbuf);
272
273       /* Allocate more space if needed */
274       if ((sock->outbuf->end - sock->outbuf->tail) < (totlen + 20)) {
275         SILC_LOG_DEBUG(("Reallocating outgoing data buffer"));
276         sock->outbuf = silc_buffer_realloc(sock->outbuf, 
277                                            sock->outbuf->truelen + 
278                                            (totlen * 2));
279       }
280
281       silc_buffer_pull_tail(sock->outbuf, totlen);
282       silc_buffer_pull(sock->outbuf, header_len + padlen);
283     }
284   }
285 }
286
287 /******************************************************************************
288
289                          Packet Reception Routines
290
291 ******************************************************************************/
292
293 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac, 
294                                uint32 sequence, SilcBuffer buffer, 
295                                bool normal);
296
297 /* Receives packet from network and reads the data into connection's
298    incoming data buffer. If the data was read directly this returns the
299    read bytes, if error occured this returns -1, if the data could not
300    be read directly at this time this returns -2 in which case the data
301    should be read again at some later time, or If EOF occured this returns
302    0. */
303
304 int silc_packet_receive(SilcSocketConnection sock)
305 {
306   int ret;
307
308   SILC_LOG_DEBUG(("Receiving packet from %s:%d [%s]", sock->hostname,
309                   sock->port, 
310                   (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
311                    sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
312                    sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
313                    "Router")));
314
315   /* Read some data from connection */
316   ret = silc_socket_read(sock);
317
318   return ret;
319 }
320
321 /* Processes and decrypts the incmoing data, and calls parser callback
322    for each received packet that will handle the actual packet parsing.
323    If more than one packet was received this calls the parser multiple
324    times.  The parser callback will get context SilcPacketParserContext
325    that includes the packet and the `parser_context' sent to this
326    function. 
327    
328    The `local_is_router' indicates whether the caller is router server
329    in which case the receiving process of a certain packet types may
330    be special.  Normal server and client must set it to FALSE.  The
331    SilcPacketParserContext will indicate also whether the received
332    packet was normal or special packet. */
333
334 void silc_packet_receive_process(SilcSocketConnection sock,
335                                  bool local_is_router,
336                                  SilcCipher cipher, SilcHmac hmac,
337                                  uint32 sequence,
338                                  SilcPacketParserCallback parser,
339                                  void *parser_context)
340 {
341   SilcPacketParserContext *parse_ctx;
342   int packetlen, paddedlen, mac_len = 0;
343   int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
344
345   if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN)
346     return;
347
348   if (hmac)
349     mac_len = silc_hmac_len(hmac);
350
351   /* Parse the packets from the data */
352   while (sock->inbuf->len > 0) {
353
354     /* Decrypt first 16 bytes of the packet */
355     if (!SILC_IS_INBUF_PENDING(sock) && cipher) {
356       /* XXX backwards support for 0.5.x
357          XXX remove in 0.7.x */
358       if (cipher->back)
359         silc_cipher_decrypt(cipher, sock->inbuf->data + 2, 
360                             sock->inbuf->data + 2, 
361                             SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
362       else
363         silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data, 
364                             SILC_PACKET_MIN_HEADER_LEN, cipher->iv);
365     }
366
367     /* Get packet lenght and full packet length with padding */
368     SILC_PACKET_LENGTH(sock->inbuf, packetlen);
369     /* XXX backwards support for 0.5.x
370        XXX remove in 0.7.x */
371     if (cipher && cipher->back) {
372       paddedlen = packetlen + SILC_PACKET_PADLEN2(packetlen, block_len);
373       paddedlen += 2;
374     } else {
375       paddedlen = packetlen + SILC_PACKET_PADLEN(packetlen, block_len);
376     }
377
378     /* Sanity checks */
379     if (packetlen < SILC_PACKET_MIN_LEN) {
380       SILC_LOG_DEBUG(("Received invalid packet, dropped"));
381       silc_buffer_clear(sock->inbuf);
382       return;
383     }
384
385     if (sock->inbuf->len < paddedlen + mac_len) {
386       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest"
387                       "(%d < %d)", sock->inbuf->len, paddedlen + mac_len));
388       SILC_SET_INBUF_PENDING(sock);
389       return;
390     }
391
392     SILC_UNSET_INBUF_PENDING(sock);
393     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
394     parse_ctx->packet = silc_packet_context_alloc();
395     parse_ctx->packet->buffer = silc_buffer_alloc(paddedlen + mac_len);
396     parse_ctx->packet->sequence = sequence++;
397     parse_ctx->sock = sock;
398     parse_ctx->context = parser_context;
399
400     silc_buffer_pull_tail(parse_ctx->packet->buffer, 
401                           SILC_BUFFER_END(parse_ctx->packet->buffer));
402     silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data, 
403                     paddedlen + mac_len);
404
405     SILC_LOG_HEXDUMP(("Incoming packet (%d) (%d bytes decrypted), len %d", 
406                       sequence - 1, block_len, paddedlen + mac_len),
407                      sock->inbuf->data, paddedlen + mac_len);
408
409     /* Check whether this is normal or special packet */
410     if (local_is_router) {
411       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
412           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
413         parse_ctx->normal = FALSE;
414       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE || 
415                (sock->inbuf->data[3] == SILC_PACKET_CHANNEL_MESSAGE &&
416                 sock->type == SILC_SOCKET_TYPE_ROUTER))
417         parse_ctx->normal = TRUE;
418     } else {
419       if (sock->inbuf->data[3] == SILC_PACKET_PRIVATE_MESSAGE &&
420           (sock->inbuf->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
421         parse_ctx->normal = FALSE;
422       else if (sock->inbuf->data[3] != SILC_PACKET_CHANNEL_MESSAGE)
423         parse_ctx->normal = TRUE;
424     }
425
426     /* Decrypt rest of the packet */
427     if (cipher)
428       silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence, 
429                           parse_ctx->packet->buffer, parse_ctx->normal);
430
431     /* Call the parser */
432     if (parser)
433       (*parser)(parse_ctx, parser_context);
434
435     /* Pull the packet from inbuf thus we'll get the next one
436        in the inbuf. */
437     silc_buffer_pull(sock->inbuf, paddedlen + mac_len);
438   }
439
440   SILC_LOG_DEBUG(("Clearing inbound buffer"));
441   silc_buffer_clear(sock->inbuf);
442 }
443
444 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. This is called
445    after packet has been totally decrypted and parsed. */
446
447 static int silc_packet_check_mac(SilcHmac hmac, SilcBuffer buffer,
448                                  uint32 sequence)
449 {
450   /* Check MAC */
451   if (hmac) {
452     unsigned char mac[32], psn[4];
453     uint32 mac_len;
454     
455     SILC_LOG_DEBUG(("Verifying MAC"));
456
457     /* Compute HMAC of packet */
458
459     memset(mac, 0, sizeof(mac));
460     silc_hmac_init(hmac);
461
462     /* XXX Backwards support for old MAC computation.
463        XXX Remove in 0.7.x */
464     if (!silc_hmac_get_b(hmac)) {
465       SILC_PUT32_MSB(sequence, psn);
466       silc_hmac_update(hmac, psn, 4);
467     }
468
469     silc_hmac_update(hmac, buffer->data, buffer->len);
470     silc_hmac_final(hmac, mac, &mac_len);
471
472     /* Compare the HMAC's (buffer->tail has the packet's HMAC) */
473     if (memcmp(mac, buffer->tail, mac_len)) {
474       SILC_LOG_ERROR(("MAC failed"));
475       assert(FALSE);
476       return FALSE;
477     }
478     
479     SILC_LOG_DEBUG(("MAC is Ok"));
480     memset(mac, 0, sizeof(mac));
481   }
482   
483   return TRUE;
484 }
485
486 /* Decrypts rest of the packet (after decrypting just the SILC header).
487    After calling this function the packet is ready to be parsed by calling 
488    silc_packet_parse. If everything goes without errors this returns TRUE,
489    if packet is malformed this returns FALSE. */
490
491 static int silc_packet_decrypt_rest(SilcCipher cipher, SilcHmac hmac,
492                                     SilcBuffer buffer)
493 {
494   if (cipher) {
495
496     /* Pull MAC from packet before decryption */
497     if (hmac) {
498       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
499         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
500       } else {
501         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
502         return FALSE;
503       }
504     }
505
506     SILC_LOG_DEBUG(("Decrypting rest of the packet"));
507
508     /* Decrypt rest of the packet */
509     silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
510     /* XXX backwards support for 0.5.x
511        XXX remove in 0.7.x */
512     if (cipher->back)
513       silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
514                           buffer->len - 2, 
515                           cipher->iv);
516     else
517       silc_cipher_decrypt(cipher, buffer->data, buffer->data, buffer->len, 
518                           cipher->iv);
519     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
520
521     SILC_LOG_HEXDUMP(("Fully decrypted packet, len %d", buffer->len),
522                      buffer->data, buffer->len);
523   }
524
525   return TRUE;
526 }
527
528 /* Decrypts rest of the SILC Packet header that has been decrypted partly
529    already. This decrypts the padding of the packet also. After calling 
530    this function the packet is ready to be parsed by calling function 
531    silc_packet_parse. This is used in special packet reception (protocol
532    defines the way of decrypting special packets). */
533
534 static int silc_packet_decrypt_rest_special(SilcCipher cipher,
535                                             SilcHmac hmac,
536                                             SilcBuffer buffer)
537 {
538   /* Decrypt rest of the header plus padding */
539   if (cipher) {
540     uint16 truelen, len1, len2, padlen, blocklen;
541
542     /* Pull MAC from packet before decryption */
543     if (hmac) {
544       if ((buffer->len - silc_hmac_len(hmac)) > SILC_PACKET_MIN_LEN) {
545         silc_buffer_push_tail(buffer, silc_hmac_len(hmac));
546       } else {
547         SILC_LOG_DEBUG(("Bad MAC length in packet, packet dropped"));
548         return FALSE;
549       }
550     }
551   
552     SILC_LOG_DEBUG(("Decrypting rest of the header"));
553
554     SILC_GET16_MSB(len1, &buffer->data[4]);
555     SILC_GET16_MSB(len2, &buffer->data[6]);
556
557     blocklen = silc_cipher_get_block_len(cipher);
558     truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
559
560     /* XXX backwards support for 0.5.x
561        XXX remove in 0.7.x */
562     if (cipher->back) {
563       padlen = SILC_PACKET_PADLEN2(truelen, blocklen);
564       len1 = (truelen + padlen) - (SILC_PACKET_MIN_HEADER_LEN);
565       
566       silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
567
568       if (len1 - 2 > buffer->len) {
569         SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
570                         "packet dropped"));
571         return FALSE;
572       }
573
574       silc_cipher_decrypt(cipher, buffer->data + 2, buffer->data + 2, 
575                           len1 - 2, cipher->iv);
576     } else {
577       blocklen = silc_cipher_get_block_len(cipher);
578       truelen = SILC_PACKET_HEADER_LEN + len1 + len2;
579       padlen = SILC_PACKET_PADLEN(truelen, blocklen);
580       len1 = (truelen + padlen) - SILC_PACKET_MIN_HEADER_LEN;
581       
582       silc_buffer_pull(buffer, SILC_PACKET_MIN_HEADER_LEN);
583
584       if (len1 > buffer->len) {
585         SILC_LOG_DEBUG(("Garbage in header of packet, bad packet length, "
586                         "packet dropped"));
587         return FALSE;
588       }
589       
590       silc_cipher_decrypt(cipher, buffer->data, buffer->data, len1, cipher->iv);
591     }
592     silc_buffer_push(buffer, SILC_PACKET_MIN_HEADER_LEN);
593   }
594
595   return TRUE;
596 }
597
598 /* Decrypts a packet. This assumes that typical SILC packet is the
599    packet to be decrypted and thus checks for normal and special SILC
600    packets and can handle both of them. This also computes and checks
601    the HMAC of the packet. If any other special or customized decryption
602    processing is required this function cannot be used. This returns
603    -1 on error, 0 when packet is normal packet and 1 when the packet
604    is special and requires special processing. 
605
606    The `check_packet' is a callback funtion that this function will 
607    call.  The callback relates to the checking whether the packet is
608    normal packet or special packet and how it should be processed.  If
609    the callback return TRUE the packet is normal and FALSE if the packet
610    is special and requires special procesing. */
611
612 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
613                                uint32 sequence, SilcBuffer buffer, 
614                                bool normal)
615 {
616   /* If the packet type is not any special type lets decrypt rest
617      of the packet here. */
618   if (normal == TRUE) {
619     /* Normal packet, decrypt rest of the packet */
620     if (!silc_packet_decrypt_rest(cipher, hmac, buffer))
621       return -1;
622
623     /* Check MAC */
624     if (!silc_packet_check_mac(hmac, buffer, sequence))
625       return -1;
626
627     return 0;
628   } else {
629     /* Packet requires special handling, decrypt rest of the header.
630        This only decrypts. */
631     if (!silc_packet_decrypt_rest_special(cipher, hmac, buffer))
632       return -1;
633
634     /* Check MAC */
635     if (!silc_packet_check_mac(hmac, buffer, sequence))
636       return -1;
637
638     return 1;
639   }
640 }
641
642 /* Parses the packet. This is called when a whole packet is ready to be
643    parsed. The buffer sent must be already decrypted before calling this 
644    function. The len argument must be the true length of the packet. This 
645    function returns the type of the packet. The data section of the 
646    buffer is parsed, not head or tail sections. */
647
648 SilcPacketType silc_packet_parse(SilcPacketContext *ctx, SilcCipher cipher)
649 {
650   SilcBuffer buffer = ctx->buffer;
651   int len, ret;
652   int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
653
654   SILC_LOG_DEBUG(("Parsing incoming packet"));
655
656   /* Check the length of the buffer */
657   if (buffer->len < SILC_PACKET_MIN_LEN) {
658     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
659     return SILC_PACKET_NONE;
660   }
661
662   /* Parse the buffer. This parses the SILC header of the packet. */
663   len = silc_buffer_unformat(buffer, 
664                              SILC_STR_UI_SHORT(&ctx->truelen),
665                              SILC_STR_UI_CHAR(&ctx->flags),
666                              SILC_STR_UI_CHAR(&ctx->type),
667                              SILC_STR_UI_SHORT(&ctx->src_id_len),
668                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
669                              SILC_STR_UI_CHAR(&ctx->src_id_type),
670                              SILC_STR_END);
671   if (len == -1)
672     return SILC_PACKET_NONE;
673
674   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
675       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
676     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
677                     ctx->src_id_len, ctx->dst_id_len));
678     return SILC_PACKET_NONE;
679   }
680
681   /* Calculate length of padding in packet */
682   ctx->padlen = SILC_PACKET_PADLEN(ctx->truelen, block_len);
683
684   silc_buffer_pull(buffer, len);
685   ret = silc_buffer_unformat(buffer, 
686                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
687                                                         ctx->src_id_len),
688                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
689                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
690                                                         ctx->dst_id_len),
691                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
692                              SILC_STR_END);
693   if (ret == -1)
694     return SILC_PACKET_NONE;
695
696   /* XXX backwards support for 0.5.x
697      XXX remove in 0.7.x */
698   silc_buffer_pull(buffer, 
699                    ctx->src_id_len + 1 + ctx->dst_id_len + ctx->padlen);
700   SILC_LOG_DEBUG(("**************** %d", buffer->len));
701   if (buffer->len == 2)
702     ctx->padlen += 2;
703   silc_buffer_push(buffer, ret);
704
705   silc_buffer_push(buffer, len);
706
707   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
708                    ctx->buffer->data, ctx->buffer->len);
709
710   /* Pull SILC header and padding from packet */
711   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
712                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
713
714   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
715
716   return ctx->type;
717 }
718
719 /* Perform special SILC Packet header parsing. This is required to some
720    packet types that have the data payload encrypted with different key
721    than the header area plus padding of the packet. Hence, this parses
722    the header in a way that it does not take the data area into account
723    and parses the header and padding area only. */
724
725 SilcPacketType silc_packet_parse_special(SilcPacketContext *ctx,
726                                          SilcCipher cipher)
727 {
728   SilcBuffer buffer = ctx->buffer;
729   int len, tmplen, ret;
730   int block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
731
732   SILC_LOG_DEBUG(("Parsing incoming packet"));
733
734   /* Check the length of the buffer */
735   if (buffer->len < SILC_PACKET_MIN_LEN) {
736     SILC_LOG_ERROR(("Bad packet length: %d, packet dropped", buffer->len));
737     return SILC_PACKET_NONE;
738   }
739
740   /* Parse the buffer. This parses the SILC header of the packet. */
741   len = silc_buffer_unformat(buffer, 
742                              SILC_STR_UI_SHORT(&ctx->truelen),
743                              SILC_STR_UI_CHAR(&ctx->flags),
744                              SILC_STR_UI_CHAR(&ctx->type),
745                              SILC_STR_UI_SHORT(&ctx->src_id_len),
746                              SILC_STR_UI_SHORT(&ctx->dst_id_len),
747                              SILC_STR_UI_CHAR(&ctx->src_id_type),
748                              SILC_STR_END);
749   if (len == -1) {
750     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
751     return SILC_PACKET_NONE;
752   }
753
754   if (ctx->src_id_len > SILC_PACKET_MAX_ID_LEN ||
755       ctx->dst_id_len > SILC_PACKET_MAX_ID_LEN) {
756     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
757                     ctx->src_id_len, ctx->dst_id_len));
758     return SILC_PACKET_NONE;
759   }
760
761   /* Calculate length of padding in packet. As this is special packet
762      the data area is not used in the padding calculation as it won't
763      be decrypted by the caller. */
764   tmplen = SILC_PACKET_HEADER_LEN + ctx->src_id_len + ctx->dst_id_len;
765   /* XXX backwards support for 0.5.x
766      XXX remove in 0.7.x */
767   if (ctx->back)
768     ctx->padlen = SILC_PACKET_PADLEN2(tmplen, block_len);
769   else
770     ctx->padlen = SILC_PACKET_PADLEN(tmplen, block_len);
771
772   silc_buffer_pull(buffer, len);
773   ret = silc_buffer_unformat(buffer, 
774                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->src_id,
775                                                         ctx->src_id_len),
776                              SILC_STR_UI_CHAR(&ctx->dst_id_type),
777                              SILC_STR_UI_XNSTRING_ALLOC(&ctx->dst_id,
778                                                         ctx->dst_id_len),
779                              SILC_STR_UI_XNSTRING(NULL, ctx->padlen),
780                              SILC_STR_END);
781   if (ret == -1) {
782     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
783     return SILC_PACKET_NONE;
784   }
785
786   silc_buffer_push(buffer, len);
787
788   SILC_LOG_HEXDUMP(("parsed packet, len %d", ctx->buffer->len), 
789                    ctx->buffer->data, ctx->buffer->len);
790
791   /* Pull SILC header and padding from packet */
792   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
793                    ctx->src_id_len + ctx->dst_id_len + ctx->padlen);
794
795   SILC_LOG_DEBUG(("Incoming packet type: %d", ctx->type));
796
797   return ctx->type;
798 }
799
800 /* Allocate packet context */
801
802 SilcPacketContext *silc_packet_context_alloc(void)
803 {
804   SilcPacketContext *ctx = silc_calloc(1, sizeof(*ctx));
805   ctx->users++;
806   return ctx;
807 }
808
809 /* Increse the reference count of the packet context. */
810
811 SilcPacketContext *silc_packet_context_dup(SilcPacketContext *ctx)
812 {
813   ctx->users++;
814   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users - 1,
815                   ctx->users));
816   return ctx;
817 }
818
819 /* Decrese the reference count of the packet context and free it only if
820    it is zero. */
821
822 void silc_packet_context_free(SilcPacketContext *ctx)
823 {
824   ctx->users--;
825   SILC_LOG_DEBUG(("Packet context %p refcnt %d->%d", ctx, ctx->users + 1,
826                   ctx->users));
827   if (ctx->users < 1)
828     {
829       if (ctx->buffer)
830         silc_buffer_free(ctx->buffer);
831       if (ctx->src_id)
832         silc_free(ctx->src_id);
833       if (ctx->dst_id)
834         silc_free(ctx->dst_id);
835       silc_free(ctx);
836     }
837 }