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