Added SILC Server library.
[silc.git] / lib / silcclient / client_prvmsg.c
1 /*
2
3   client_prvmsg.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2004 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 /* $Id$ */
20 /* This file includes the private message sending and receiving routines
21    and private message key handling routines. */
22
23 #include "silc.h"
24 #include "silcclient.h"
25 #include "client_internal.h"
26
27 /* Sends private message to remote client. If private message key has
28    not been set with this client then the message will be encrypted using
29    normal session keys. Private messages are special packets in SILC
30    network hence we need this own function for them. This is similiar
31    to silc_client_packet_send_to_channel except that we send private
32    message. The `data' is the private message. If the `force_send' is
33    TRUE the packet is sent immediately. */
34
35 SilcBool silc_client_send_private_message(SilcClient client,
36                                       SilcClientConnection conn,
37                                       SilcClientEntry client_entry,
38                                       SilcMessageFlags flags,
39                                       unsigned char *data,
40                                       SilcUInt32 data_len,
41                                       SilcBool force_send)
42 {
43   SilcSocketConnection sock;
44   SilcBuffer buffer;
45   SilcPacketContext packetdata;
46   const SilcBufferStruct packet;
47   SilcCipher cipher;
48   SilcHmac hmac;
49   int block_len;
50   SilcBool ret = FALSE;
51
52   assert(client && conn && client_entry);
53   sock = conn->sock;
54   SILC_LOG_DEBUG(("Sending private message"));
55
56   /* Encode private message payload */
57   buffer = silc_message_payload_encode(flags, data, data_len,
58                                        !client_entry->send_key ? FALSE :
59                                        !client_entry->generated,
60                                        TRUE, client_entry->send_key,
61                                        client_entry->hmac_send,
62                                        client->rng, NULL, client->private_key,
63                                        client->sha1hash);
64   if (!buffer) {
65     SILC_LOG_ERROR(("Error encoding private message"));
66     return FALSE;
67   }
68
69   /* If we don't have private message specific key then private messages
70      are just as any normal packet thus call normal packet sending.  If
71      the key exist then the encryption process is a bit different and
72      will be done in the rest of this function. */
73   if (!client_entry->send_key) {
74     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
75                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
76                             buffer->data, buffer->len, force_send);
77     ret = TRUE;
78     goto out;
79   }
80
81   /* We have private message specific key */
82
83   /* Get data used in the encryption */
84   cipher = conn->internal->send_key;
85   hmac = conn->internal->hmac_send;
86   block_len = silc_cipher_get_block_len(cipher);
87
88   /* Set the packet context pointers. */
89   data = buffer->data;
90   data_len = buffer->len;
91   packetdata.flags = SILC_PACKET_FLAG_PRIVMSG_KEY;
92   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
93   packetdata.src_id = conn->local_id_data;
94   packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
95   packetdata.src_id_type = SILC_ID_CLIENT;
96   packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
97   packetdata.dst_id_len = silc_id_get_len(client_entry->id, SILC_ID_CLIENT);
98   packetdata.dst_id_type = SILC_ID_CLIENT;
99   data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
100                                  packetdata.src_id_len +
101                                  packetdata.dst_id_len);
102   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
103     packetdata.src_id_len + packetdata.dst_id_len;
104   SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
105                       packetdata.src_id_len +
106                       packetdata.dst_id_len), block_len, packetdata.padlen);
107
108   /* Create the outgoing packet */
109   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
110                             data, data_len, (const SilcBuffer)&packet)) {
111     SILC_LOG_ERROR(("Error assembling packet"));
112     goto out;
113   }
114
115   /* Encrypt the header and padding of the packet. */
116   silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
117                       (SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
118                       packetdata.src_id_len + packetdata.dst_id_len +
119                       packetdata.padlen);
120
121   SILC_LOG_HEXDUMP(("Private message packet, len %d", packet.len),
122                    packet.data, packet.len);
123
124   /* Now actually send the packet */
125   silc_client_packet_send_real(client, sock, force_send);
126
127   /* Check for mandatory rekey */
128   if (conn->internal->psn_send == SILC_CLIENT_REKEY_THRESHOLD)
129     silc_schedule_task_add(client->schedule, sock->sock,
130                            silc_client_rekey_callback, sock, 0, 1,
131                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
132
133   silc_free(packetdata.dst_id);
134
135   ret = TRUE;
136
137  out:
138   silc_buffer_free(buffer);
139
140   return ret;
141 }
142
143 static void silc_client_private_message_cb(SilcClient client,
144                                            SilcClientConnection conn,
145                                            SilcClientEntry *clients,
146                                            SilcUInt32 clients_count,
147                                            void *context)
148 {
149   SilcPacketContext *packet = (SilcPacketContext *)context;
150
151   if (!clients) {
152     silc_packet_context_free(packet);
153     return;
154   }
155
156   silc_client_private_message(client, conn->sock, packet);
157   silc_packet_context_free(packet);
158 }
159
160 /* Private message received. This processes the private message and
161    finally displays it on the screen. */
162
163 void silc_client_private_message(SilcClient client,
164                                  SilcSocketConnection sock,
165                                  SilcPacketContext *packet)
166 {
167   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
168   SilcMessagePayload payload = NULL;
169   SilcClientID *remote_id = NULL;
170   SilcClientEntry remote_client;
171   SilcMessageFlags flags;
172   unsigned char *message;
173   SilcUInt32 message_len;
174   SilcCipher cipher = NULL;
175   SilcHmac hmac = NULL;
176
177   if (packet->src_id_type != SILC_ID_CLIENT)
178     goto out;
179
180   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
181                              SILC_ID_CLIENT);
182   if (!remote_id)
183     goto out;
184
185   /* Check whether we know this client already */
186   remote_client = silc_client_get_client_by_id(client, conn, remote_id);
187   if (!remote_client || !remote_client->nickname) {
188     if (remote_client) {
189       if (remote_client->status & SILC_CLIENT_STATUS_RESOLVING) {
190         remote_client->status &= ~SILC_CLIENT_STATUS_RESOLVING;
191         goto out;
192       }
193       remote_client->status |= SILC_CLIENT_STATUS_RESOLVING;
194       remote_client->resolve_cmd_ident = conn->cmd_ident + 1;
195     }
196
197     /* Resolve the client info */
198     silc_client_get_client_by_id_resolve(client, conn, remote_id, NULL,
199                                          silc_client_private_message_cb,
200                                          silc_packet_context_dup(packet));
201     return;
202   }
203
204   cipher = remote_client->receive_key;
205   hmac = remote_client->hmac_receive;
206   if (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY && !cipher && !hmac) {
207     silc_free(remote_id);
208     return;
209   }
210
211   /* Parse the payload and decrypt it also if private message key is set */
212   payload = silc_message_payload_parse(packet->buffer->data,
213                                        packet->buffer->len, TRUE,
214                                        !remote_client->generated,
215                                        cipher, hmac);
216   if (!payload) {
217     silc_free(remote_id);
218     return;
219   }
220
221   flags = silc_message_get_flags(payload);
222
223   /* Pass the private message to application */
224   message = silc_message_get_data(payload, &message_len);
225   client->internal->ops->private_message(client, conn, remote_client, payload,
226                                          flags, message, message_len);
227
228   /* See if we are away (gone). If we are away we will reply to the
229      sender with the set away message. */
230   if (conn->internal->away && conn->internal->away->away &&
231       !(flags & SILC_MESSAGE_FLAG_NOREPLY)) {
232     /* If it's me, ignore */
233     if (SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
234       goto out;
235
236     /* Send the away message */
237     silc_client_send_private_message(client, conn, remote_client,
238                                      SILC_MESSAGE_FLAG_AUTOREPLY |
239                                      SILC_MESSAGE_FLAG_NOREPLY,
240                                      conn->internal->away->away,
241                                      strlen(conn->internal->away->away), TRUE);
242   }
243
244  out:
245   if (payload)
246     silc_message_payload_free(payload);
247   silc_free(remote_id);
248 }
249
250 /* Function that actually employes the received private message key */
251
252 static void silc_client_private_message_key_cb(SilcClient client,
253                                                SilcClientConnection conn,
254                                                SilcClientEntry *clients,
255                                                SilcUInt32 clients_count,
256                                                void *context)
257 {
258   SilcPacketContext *packet = (SilcPacketContext *)context;
259   unsigned char *key;
260   SilcUInt16 key_len;
261   unsigned char *cipher = NULL, *hmac = NULL;
262   int ret;
263
264   if (!clients)
265     goto out;
266
267   /* Parse the private message key payload */
268   ret = silc_buffer_unformat(packet->buffer,
269                              SILC_STR_UI16_NSTRING(&key, &key_len),
270                              SILC_STR_UI16_STRING_ALLOC(&cipher),
271                              SILC_STR_UI16_STRING_ALLOC(&hmac),
272                              SILC_STR_END);
273   if (!ret)
274     goto out;
275
276   if (key_len > packet->buffer->len)
277     goto out;
278
279   /* Mark that we are responder */
280   clients[0]->prv_resp = TRUE;
281
282  out:
283   silc_free(cipher);
284   silc_free(hmac);
285   silc_packet_context_free(packet);
286 }
287
288 /* Processes incoming Private Message Key payload to indicate that the
289    sender whishes to set up a static private message key. */
290
291 void silc_client_private_message_key(SilcClient client,
292                                      SilcSocketConnection sock,
293                                      SilcPacketContext *packet)
294 {
295   SilcClientID *remote_id;
296
297   if (packet->src_id_type != SILC_ID_CLIENT)
298     return;
299
300   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
301                              SILC_ID_CLIENT);
302   if (!remote_id)
303     return;
304
305   silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
306                                        NULL,
307                                        silc_client_private_message_key_cb,
308                                        silc_packet_context_dup(packet));
309   silc_free(remote_id);
310 }
311
312 /* Adds private message key to the client library. The key will be used to
313    encrypt all private message between the client and the remote client
314    indicated by the `client_entry'. If the `key' is NULL and the boolean
315    value `generate_key' is TRUE the library will generate random key.
316    The `key' maybe for example pre-shared-key, passphrase or similar.
317    The `cipher' and `hmac' MAY be provided but SHOULD be NULL to assure
318    that the requirements of the SILC protocol are met. The API, however,
319    allows to allocate any cipher and HMAC.
320
321    If `responder' is TRUE then the sending and receiving keys will be
322    set according the client being the receiver of the private key.  If
323    FALSE the client is being the sender (or negotiator) of the private
324    key.
325
326    It is not necessary to set key for normal private message usage. If the
327    key is not set then the private messages are encrypted using normal
328    session keys. Setting the private key, however, increases the security.
329
330    Returns FALSE if the key is already set for the `client_entry', TRUE
331    otherwise. */
332
333 SilcBool silc_client_add_private_message_key(SilcClient client,
334                                          SilcClientConnection conn,
335                                          SilcClientEntry client_entry,
336                                          const char *cipher,
337                                          const char *hmac,
338                                          unsigned char *key,
339                                          SilcUInt32 key_len,
340                                          SilcBool generate_key,
341                                          SilcBool responder)
342 {
343   unsigned char private_key[32];
344   SilcUInt32 len;
345   int i;
346   SilcSKEKeyMaterial *keymat;
347
348   assert(client && client_entry);
349
350   /* Return FALSE if key already set */
351   if (client_entry->send_key && client_entry->receive_key)
352     return FALSE;
353
354   if (!cipher)
355     cipher = SILC_DEFAULT_CIPHER;
356   if (!hmac)
357     hmac = SILC_DEFAULT_HMAC;
358
359   /* Check the requested cipher and HMAC */
360   if (!silc_cipher_is_supported(cipher))
361     return FALSE;
362   if (!silc_hmac_is_supported(hmac))
363     return FALSE;
364
365   /* Generate key if not provided */
366   if (generate_key == TRUE) {
367     len = 32;
368     for (i = 0; i < len; i++)
369       private_key[i] = silc_rng_get_byte_fast(client->rng);
370     key = private_key;
371     key_len = len;
372     client_entry->generated = TRUE;
373   }
374
375   /* Save the key */
376   client_entry->key = silc_memdup(key, key_len);
377   client_entry->key_len = key_len;
378
379   /* Produce the key material as the protocol defines */
380   keymat = silc_calloc(1, sizeof(*keymat));
381   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
382                                          client->sha1hash, keymat)
383       != SILC_SKE_STATUS_OK)
384     return FALSE;
385
386   /* Allocate the cipher and HMAC */
387   silc_cipher_alloc(cipher, &client_entry->send_key);
388   silc_cipher_alloc(cipher, &client_entry->receive_key);
389   silc_hmac_alloc(hmac, NULL, &client_entry->hmac_send);
390   silc_hmac_alloc(hmac, NULL, &client_entry->hmac_receive);
391
392   /* Set the keys */
393   if (responder == TRUE) {
394     silc_cipher_set_key(client_entry->send_key, keymat->receive_enc_key,
395                         keymat->enc_key_len);
396     silc_cipher_set_iv(client_entry->send_key, keymat->receive_iv);
397     silc_cipher_set_key(client_entry->receive_key, keymat->send_enc_key,
398                         keymat->enc_key_len);
399     silc_cipher_set_iv(client_entry->receive_key, keymat->send_iv);
400     silc_hmac_set_key(client_entry->hmac_send, keymat->receive_hmac_key,
401                       keymat->hmac_key_len);
402     silc_hmac_set_key(client_entry->hmac_receive, keymat->send_hmac_key,
403                       keymat->hmac_key_len);
404   } else {
405     silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
406                         keymat->enc_key_len);
407     silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
408     silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
409                         keymat->enc_key_len);
410     silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
411     silc_hmac_set_key(client_entry->hmac_send, keymat->send_hmac_key,
412                       keymat->hmac_key_len);
413     silc_hmac_set_key(client_entry->hmac_receive, keymat->receive_hmac_key,
414                       keymat->hmac_key_len);
415   }
416
417   /* Free the key material */
418   silc_ske_free_key_material(keymat);
419
420   return TRUE;
421 }
422
423 /* Same as above but takes the key material from the SKE key material
424    structure. This structure is received if the application uses the
425    silc_client_send_key_agreement to negotiate the key material. The
426    `cipher' and `hmac' SHOULD be provided as it is negotiated also in
427    the SKE protocol. */
428
429 SilcBool silc_client_add_private_message_key_ske(SilcClient client,
430                                              SilcClientConnection conn,
431                                              SilcClientEntry client_entry,
432                                              const char *cipher,
433                                              const char *hmac,
434                                              SilcSKEKeyMaterial *key,
435                                              SilcBool responder)
436 {
437   assert(client && client_entry);
438
439   /* Return FALSE if key already set */
440   if (client_entry->send_key && client_entry->receive_key)
441     return FALSE;
442
443   if (!cipher)
444     cipher = SILC_DEFAULT_CIPHER;
445   if (!hmac)
446     hmac = SILC_DEFAULT_HMAC;
447
448   /* Check the requested cipher and HMAC */
449   if (!silc_cipher_is_supported(cipher))
450     return FALSE;
451   if (!silc_hmac_is_supported(hmac))
452     return FALSE;
453
454   client_entry->generated = TRUE;
455
456   /* Allocate the cipher and HMAC */
457   silc_cipher_alloc(cipher, &client_entry->send_key);
458   silc_cipher_alloc(cipher, &client_entry->receive_key);
459   silc_hmac_alloc(hmac, NULL, &client_entry->hmac_send);
460   silc_hmac_alloc(hmac, NULL, &client_entry->hmac_receive);
461
462   /* Set the keys */
463   if (responder == TRUE) {
464     silc_cipher_set_key(client_entry->send_key, key->receive_enc_key,
465                         key->enc_key_len);
466     silc_cipher_set_iv(client_entry->send_key, key->receive_iv);
467     silc_cipher_set_key(client_entry->receive_key, key->send_enc_key,
468                         key->enc_key_len);
469     silc_cipher_set_iv(client_entry->receive_key, key->send_iv);
470     silc_hmac_set_key(client_entry->hmac_send, key->receive_hmac_key,
471                       key->hmac_key_len);
472     silc_hmac_set_key(client_entry->hmac_receive, key->send_hmac_key,
473                       key->hmac_key_len);
474   } else {
475     silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
476                         key->enc_key_len);
477     silc_cipher_set_iv(client_entry->send_key, key->send_iv);
478     silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
479                         key->enc_key_len);
480     silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
481     silc_hmac_set_key(client_entry->hmac_send, key->send_hmac_key,
482                       key->hmac_key_len);
483     silc_hmac_set_key(client_entry->hmac_receive, key->receive_hmac_key,
484                       key->hmac_key_len);
485   }
486
487   return TRUE;
488 }
489
490 /* Sends private message key indicator.  The sender of this packet is
491    going to be the initiator, if and when, the users set up a static
492    private message key (not Key Agreement). */
493
494 SilcBool silc_client_send_private_message_key_request(SilcClient client,
495                                                   SilcClientConnection conn,
496                                                   SilcClientEntry client_entry)
497 {
498   SilcSocketConnection sock;
499   SilcBuffer buffer;
500   int cipher_len, hmac_len;
501   const char *cipher, *hmac;
502
503   assert(client && conn && client_entry);
504
505   sock = conn->sock;
506   if (!client_entry->send_key || !client_entry->key)
507     return FALSE;
508
509   SILC_LOG_DEBUG(("Sending private message key indicator"));
510
511   cipher = silc_cipher_get_name(client_entry->send_key);
512   cipher_len = strlen(cipher);
513   hmac = silc_hmac_get_name(client_entry->hmac_send);
514   hmac_len = strlen(hmac);
515
516   /* Create private message key payload */
517   buffer = silc_buffer_alloc_size(4 + cipher_len + hmac_len);
518   silc_buffer_format(buffer,
519                      SILC_STR_UI_SHORT(cipher_len),
520                      SILC_STR_UI_XNSTRING(cipher,
521                                           cipher_len),
522                      SILC_STR_UI_SHORT(hmac_len),
523                      SILC_STR_UI_XNSTRING(hmac,
524                                           hmac_len),
525                      SILC_STR_END);
526
527   /* Send the packet */
528   silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
529                           client_entry->id, SILC_ID_CLIENT, NULL, NULL,
530                           buffer->data, buffer->len, TRUE);
531   silc_free(buffer);
532
533   return TRUE;
534 }
535
536 /* Removes the private message from the library. The key won't be used
537    after this to protect the private messages with the remote `client_entry'
538    client. Returns FALSE on error, TRUE otherwise. */
539
540 SilcBool silc_client_del_private_message_key(SilcClient client,
541                                         SilcClientConnection conn,
542                                         SilcClientEntry client_entry)
543 {
544   assert(client && client_entry);
545
546   if (!client_entry->send_key && !client_entry->receive_key)
547     return FALSE;
548
549   silc_cipher_free(client_entry->send_key);
550   silc_cipher_free(client_entry->receive_key);
551
552   if (client_entry->key) {
553     memset(client_entry->key, 0, client_entry->key_len);
554     silc_free(client_entry->key);
555   }
556
557   client_entry->send_key = NULL;
558   client_entry->receive_key = NULL;
559   client_entry->key = NULL;
560
561   return TRUE;
562 }
563
564 /* Returns array of set private message keys associated to the connection
565    `conn'. Returns allocated SilcPrivateMessageKeys array and the array
566    count to the `key_count' argument. The array must be freed by the caller
567    by calling the silc_client_free_private_message_keys function. Note:
568    the keys returned in the array is in raw format. It might not be desired
569    to show the keys as is. The application might choose not to show the keys
570    at all or to show the fingerprints of the keys. */
571
572 SilcPrivateMessageKeys
573 silc_client_list_private_message_keys(SilcClient client,
574                                       SilcClientConnection conn,
575                                       SilcUInt32 *key_count)
576 {
577   SilcPrivateMessageKeys keys;
578   SilcUInt32 count = 0;
579   SilcIDCacheEntry id_cache;
580   SilcIDCacheList list;
581   SilcClientEntry entry;
582
583   assert(client && conn);
584
585   if (!silc_idcache_get_all(conn->internal->client_cache, &list))
586     return NULL;
587
588   if (!silc_idcache_list_count(list)) {
589     silc_idcache_list_free(list);
590     return NULL;
591   }
592
593   keys = silc_calloc(silc_idcache_list_count(list), sizeof(*keys));
594
595   silc_idcache_list_first(list, &id_cache);
596   while (id_cache) {
597     entry = (SilcClientEntry)id_cache->context;
598
599     if (entry->send_key) {
600       keys[count].client_entry = entry;
601       keys[count].cipher = (char *)silc_cipher_get_name(entry->send_key);
602       keys[count].key = entry->generated == FALSE ? entry->key : NULL;
603       keys[count].key_len = entry->generated == FALSE ? entry->key_len : 0;
604       count++;
605     }
606
607     if (!silc_idcache_list_next(list, &id_cache))
608       break;
609   }
610
611   if (key_count)
612     *key_count = count;
613
614   return keys;
615 }
616
617 /* Frees the SilcPrivateMessageKeys array returned by the function
618    silc_client_list_private_message_keys. */
619
620 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
621                                            SilcUInt32 key_count)
622 {
623   silc_free(keys);
624 }
625
626 /* Sets away `message'.  The away message may be set when the client's
627    mode is changed to SILC_UMODE_GONE and the client whishes to reply
628    to anyone who sends private message.  The `message' will be sent
629    automatically back to the the client who send private message.  If
630    away message is already set this replaces the old message with the
631    new one.  If `message' is NULL the old away message is removed.
632    The sender may freely free the memory of the `message'. */
633
634 void silc_client_set_away_message(SilcClient client,
635                                   SilcClientConnection conn,
636                                   char *message)
637 {
638   assert(client && conn);
639
640   if (!message && conn->internal->away) {
641     silc_free(conn->internal->away->away);
642     silc_free(conn->internal->away);
643     conn->internal->away = NULL;
644   }
645
646   if (message) {
647     if (!conn->internal->away)
648       conn->internal->away = silc_calloc(1, sizeof(*conn->internal->away));
649     if (conn->internal->away->away)
650       silc_free(conn->internal->away->away);
651     conn->internal->away->away = strdup(message);
652   }
653 }