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