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