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   SilcClientID *remote_id = NULL;
151   SilcClientEntry remote_client;
152   SilcMessageFlags flags;
153
154   if (packet->src_id_type != SILC_ID_CLIENT)
155     goto out;
156
157   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
158                              SILC_ID_CLIENT);
159   if (!remote_id)
160     goto out;
161
162   /* Check whether we know this client already */
163   remote_client = silc_client_get_client_by_id(client, conn, remote_id);
164   if (!remote_client || !remote_client->nickname) {
165     if (remote_client) {
166       if (remote_client->status & SILC_CLIENT_STATUS_RESOLVING) {
167         remote_client->status &= ~SILC_CLIENT_STATUS_RESOLVING;
168         goto out;
169       }
170       remote_client->status |= SILC_CLIENT_STATUS_RESOLVING;
171     }
172
173     /* Resolve the client info */
174     silc_client_get_client_by_id_resolve(client, conn, remote_id,
175                                          silc_client_private_message_cb,
176                                          silc_packet_context_dup(packet));
177     return;
178   }
179
180   /* Parse the payload and decrypt it also if private message key is set */
181   payload = silc_private_message_payload_parse(packet->buffer->data,
182                                                packet->buffer->len,
183                                                remote_client->receive_key);
184   if (!payload) {
185     silc_free(remote_id);
186     return;
187   }
188
189   flags = silc_private_message_get_flags(payload);
190
191   /* Pass the private message to application */
192   client->internal->ops->private_message(
193                                  client, conn, remote_client, flags,
194                                  silc_private_message_get_message(payload, 
195                                                                   NULL));
196
197   /* See if we are away (gone). If we are away we will reply to the
198      sender with the set away message. */
199   if (conn->away && conn->away->away && !(flags & SILC_MESSAGE_FLAG_NOREPLY)) {
200     /* If it's me, ignore */
201     if (SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
202       goto out;
203
204     /* Send the away message */
205     silc_client_send_private_message(client, conn, remote_client,
206                                      SILC_MESSAGE_FLAG_AUTOREPLY |
207                                      SILC_MESSAGE_FLAG_NOREPLY,
208                                      conn->away->away,
209                                      strlen(conn->away->away), TRUE);
210   }
211
212  out:
213   if (payload)
214     silc_private_message_payload_free(payload);
215   silc_free(remote_id);
216 }
217
218 /* Function that actually employes the received private message key */
219
220 static void silc_client_private_message_key_cb(SilcClient client,
221                                                SilcClientConnection conn,
222                                                SilcClientEntry *clients,
223                                                uint32 clients_count,
224                                                void *context)
225 {
226   SilcPacketContext *packet = (SilcPacketContext *)context;
227   unsigned char *key;
228   uint16 key_len;
229   unsigned char *cipher;
230   int ret;
231
232   if (!clients)
233     goto out;
234
235   /* Parse the private message key payload */
236   ret = silc_buffer_unformat(packet->buffer,
237                              SILC_STR_UI16_NSTRING(&key, &key_len),
238                              SILC_STR_UI16_STRING(&cipher),
239                              SILC_STR_END);
240   if (!ret)
241     goto out;
242
243   if (key_len > packet->buffer->len)
244     goto out;
245
246   /* Now take the key in use */
247   if (!silc_client_add_private_message_key(client, conn, clients[0],
248                                            cipher, key, key_len, FALSE, TRUE))
249     goto out;
250
251   /* Print some info for application */
252   client->internal->ops->say(
253                      client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
254                      "Received private message key from %s%s%s %s%s%s", 
255                      clients[0]->nickname,
256                      clients[0]->server ? "@" : "",
257                      clients[0]->server ? clients[0]->server : "",
258                      clients[0]->username ? "(" : "",
259                      clients[0]->username ? clients[0]->username : "",
260                      clients[0]->username ? ")" : "");
261
262  out:
263   silc_packet_context_free(packet);
264 }
265
266 /* Processes incoming Private Message Key payload. The libary always
267    accepts the key and takes it into use. */
268
269 void silc_client_private_message_key(SilcClient client,
270                                      SilcSocketConnection sock,
271                                      SilcPacketContext *packet)
272 {
273   SilcClientID *remote_id;
274
275   if (packet->src_id_type != SILC_ID_CLIENT)
276     return;
277
278   remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
279                              SILC_ID_CLIENT);
280   if (!remote_id)
281     return;
282
283   silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
284                                        silc_client_private_message_key_cb,
285                                        silc_packet_context_dup(packet));
286   silc_free(remote_id);
287 }
288
289 /* Adds private message key to the client library. The key will be used to
290    encrypt all private message between the client and the remote client
291    indicated by the `client_entry'. If the `key' is NULL and the boolean
292    value `generate_key' is TRUE the library will generate random key.
293    The `key' maybe for example pre-shared-key, passphrase or similar.
294    The `cipher' MAY be provided but SHOULD be NULL to assure that the
295    requirements of the SILC protocol are met. The API, however, allows
296    to allocate any cipher.
297
298    If `responder' is TRUE then the sending and receiving keys will be
299    set according the client being the receiver of the private key.  If
300    FALSE the client is being the sender (or negotiator) of the private
301    key.
302
303    It is not necessary to set key for normal private message usage. If the
304    key is not set then the private messages are encrypted using normal
305    session keys. Setting the private key, however, increases the security. 
306
307    Returns FALSE if the key is already set for the `client_entry', TRUE
308    otherwise. */
309
310 int silc_client_add_private_message_key(SilcClient client,
311                                         SilcClientConnection conn,
312                                         SilcClientEntry client_entry,
313                                         char *cipher,
314                                         unsigned char *key,
315                                         uint32 key_len,
316                                         bool generate_key,
317                                         bool responder)
318 {
319   unsigned char private_key[32];
320   uint32 len;
321   int i;
322   SilcSKEKeyMaterial *keymat;
323
324   assert(client_entry);
325
326   /* Return FALSE if key already set */
327   if (client_entry->send_key && client_entry->receive_key)
328     return FALSE;
329
330   if (!cipher)
331     cipher = SILC_DEFAULT_CIPHER;
332
333   /* Check the requested cipher */
334   if (!silc_cipher_is_supported(cipher))
335     return FALSE;
336
337   /* Generate key if not provided */
338   if (generate_key == TRUE) {
339     len = 32;
340     for (i = 0; i < len; i++) private_key[i] = silc_rng_get_byte(client->rng);
341     key = private_key;
342     key_len = len;
343     client_entry->generated = TRUE;
344   }
345
346   /* Save the key */
347   client_entry->key = silc_memdup(key, key_len);
348   client_entry->key_len = key_len;
349
350   /* Produce the key material as the protocol defines */
351   keymat = silc_calloc(1, sizeof(*keymat));
352   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
353                                          client->internal->md5hash, keymat) 
354       != SILC_SKE_STATUS_OK)
355     return FALSE;
356
357   /* Allocate the ciphers */
358   silc_cipher_alloc(cipher, &client_entry->send_key);
359   silc_cipher_alloc(cipher, &client_entry->receive_key);
360
361   /* Set the keys */
362   if (responder == TRUE) {
363     silc_cipher_set_key(client_entry->send_key, keymat->receive_enc_key,
364                         keymat->enc_key_len);
365     silc_cipher_set_iv(client_entry->send_key, keymat->receive_iv);
366     silc_cipher_set_key(client_entry->receive_key, keymat->send_enc_key,
367                         keymat->enc_key_len);
368     silc_cipher_set_iv(client_entry->receive_key, keymat->send_iv);
369   } else {
370     silc_cipher_set_key(client_entry->send_key, keymat->send_enc_key,
371                         keymat->enc_key_len);
372     silc_cipher_set_iv(client_entry->send_key, keymat->send_iv);
373     silc_cipher_set_key(client_entry->receive_key, keymat->receive_enc_key,
374                         keymat->enc_key_len);
375     silc_cipher_set_iv(client_entry->receive_key, keymat->receive_iv);
376   }
377
378   /* Free the key material */
379   silc_ske_free_key_material(keymat);
380
381   return TRUE;
382 }
383
384 /* Same as above but takes the key material from the SKE key material
385    structure. This structure is received if the application uses the
386    silc_client_send_key_agreement to negotiate the key material. The
387    `cipher' SHOULD be provided as it is negotiated also in the SKE
388    protocol. */
389
390 int silc_client_add_private_message_key_ske(SilcClient client,
391                                             SilcClientConnection conn,
392                                             SilcClientEntry client_entry,
393                                             char *cipher,
394                                             SilcSKEKeyMaterial *key,
395                                             bool responder)
396 {
397   assert(client_entry);
398
399   /* Return FALSE if key already set */
400   if (client_entry->send_key && client_entry->receive_key)
401     return FALSE;
402
403   if (!cipher)
404     cipher = SILC_DEFAULT_CIPHER;
405
406   /* Check the requested cipher */
407   if (!silc_cipher_is_supported(cipher))
408     return FALSE;
409
410   /* Allocate the ciphers */
411   silc_cipher_alloc(cipher, &client_entry->send_key);
412   silc_cipher_alloc(cipher, &client_entry->receive_key);
413
414   /* Set the keys */
415   if (responder == TRUE) {
416     silc_cipher_set_key(client_entry->send_key, key->receive_enc_key,
417                         key->enc_key_len);
418     silc_cipher_set_iv(client_entry->send_key, key->receive_iv);
419     silc_cipher_set_key(client_entry->receive_key, key->send_enc_key,
420                         key->enc_key_len);
421     silc_cipher_set_iv(client_entry->receive_key, key->send_iv);
422   } else {
423     silc_cipher_set_key(client_entry->send_key, key->send_enc_key,
424                         key->enc_key_len);
425     silc_cipher_set_iv(client_entry->send_key, key->send_iv);
426     silc_cipher_set_key(client_entry->receive_key, key->receive_enc_key,
427                         key->enc_key_len);
428     silc_cipher_set_iv(client_entry->receive_key, key->receive_iv);
429   }
430
431   return TRUE;
432 }
433
434 /* Sends private message key payload to the remote client indicated by
435    the `client_entry'. If the `force_send' is TRUE the packet is sent
436    immediately. Returns FALSE if error occurs, TRUE otherwise. The
437    application should call this function after setting the key to the
438    client.
439
440    Note that the key sent using this function is sent to the remote client
441    through the SILC network. The packet is protected using normal session
442    keys. */
443
444 int silc_client_send_private_message_key(SilcClient client,
445                                          SilcClientConnection conn,
446                                          SilcClientEntry client_entry,
447                                          int force_send)
448 {
449   SilcSocketConnection sock = conn->sock;
450   SilcBuffer buffer;
451   int cipher_len;
452
453   if (!client_entry->send_key || !client_entry->key)
454     return FALSE;
455
456   SILC_LOG_DEBUG(("Sending private message key"));
457
458   cipher_len = strlen(client_entry->send_key->cipher->name);
459
460   /* Create private message key payload */
461   buffer = silc_buffer_alloc(2 + client_entry->key_len);
462   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
463   silc_buffer_format(buffer,
464                      SILC_STR_UI_SHORT(client_entry->key_len),
465                      SILC_STR_UI_XNSTRING(client_entry->key, 
466                                           client_entry->key_len),
467                      SILC_STR_UI_SHORT(cipher_len),
468                      SILC_STR_UI_XNSTRING(client_entry->send_key->cipher->name,
469                                           cipher_len),
470                      SILC_STR_END);
471
472   /* Send the packet */
473   silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
474                           client_entry->id, SILC_ID_CLIENT, NULL, NULL,
475                           buffer->data, buffer->len, force_send);
476   silc_free(buffer);
477
478   return TRUE;
479 }
480
481 /* Removes the private message from the library. The key won't be used
482    after this to protect the private messages with the remote `client_entry'
483    client. Returns FALSE on error, TRUE otherwise. */
484
485 int silc_client_del_private_message_key(SilcClient client,
486                                         SilcClientConnection conn,
487                                         SilcClientEntry client_entry)
488 {
489   assert(client_entry);
490
491   if (!client_entry->send_key && !client_entry->receive_key)
492     return FALSE;
493
494   silc_cipher_free(client_entry->send_key);
495   silc_cipher_free(client_entry->receive_key);
496
497   if (client_entry->key) {
498     memset(client_entry->key, 0, client_entry->key_len);
499     silc_free(client_entry->key);
500   }
501
502   client_entry->send_key = NULL;
503   client_entry->receive_key = NULL;
504   client_entry->key = NULL;
505
506   return TRUE;
507 }
508
509 /* Returns array of set private message keys associated to the connection
510    `conn'. Returns allocated SilcPrivateMessageKeys array and the array
511    count to the `key_count' argument. The array must be freed by the caller
512    by calling the silc_client_free_private_message_keys function. Note: 
513    the keys returned in the array is in raw format. It might not be desired
514    to show the keys as is. The application might choose not to show the keys
515    at all or to show the fingerprints of the keys. */
516
517 SilcPrivateMessageKeys
518 silc_client_list_private_message_keys(SilcClient client,
519                                       SilcClientConnection conn,
520                                       uint32 *key_count)
521 {
522   SilcPrivateMessageKeys keys;
523   uint32 count = 0;
524   SilcIDCacheEntry id_cache;
525   SilcIDCacheList list;
526   SilcClientEntry entry;
527
528   if (!silc_idcache_get_all(conn->client_cache, &list))
529     return NULL;
530
531   if (!silc_idcache_list_count(list)) {
532     silc_idcache_list_free(list);
533     return NULL;
534   }
535
536   keys = silc_calloc(silc_idcache_list_count(list), sizeof(*keys));
537
538   silc_idcache_list_first(list, &id_cache);
539   while (id_cache) {
540     entry = (SilcClientEntry)id_cache->context;
541
542     if (entry->send_key) {
543       keys[count].client_entry = entry;
544       keys[count].cipher = entry->send_key->cipher->name;
545       keys[count].key = entry->generated == FALSE ? entry->key : NULL;
546       keys[count].key_len = entry->generated == FALSE ? entry->key_len : 0;
547       count++;
548     }
549
550     if (!silc_idcache_list_next(list, &id_cache))
551       break;
552   }
553
554   if (key_count)
555     *key_count = count;
556
557   return keys;
558 }
559
560 /* Frees the SilcPrivateMessageKeys array returned by the function
561    silc_client_list_private_message_keys. */
562
563 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
564                                            uint32 key_count)
565 {
566   silc_free(keys);
567 }
568
569 /* Sets away `message'.  The away message may be set when the client's
570    mode is changed to SILC_UMODE_GONE and the client whishes to reply
571    to anyone who sends private message.  The `message' will be sent
572    automatically back to the the client who send private message.  If
573    away message is already set this replaces the old message with the
574    new one.  If `message' is NULL the old away message is removed. 
575    The sender may freely free the memory of the `message'. */
576
577 void silc_client_set_away_message(SilcClient client,
578                                   SilcClientConnection conn,
579                                   char *message)
580 {
581   if (!message && conn->away) {
582     silc_free(conn->away->away);
583     silc_free(conn->away);
584     conn->away = NULL;
585   }
586
587   if (message) {
588     if (!conn->away)
589       conn->away = silc_calloc(1, sizeof(*conn->away));
590     if (conn->away->away)
591       silc_free(conn->away->away);
592     conn->away->away = strdup(message);
593   }
594 }