silc-client: handle prompt abort better
[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 - 2014 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
21 #include "silc.h"
22 #include "silcclient.h"
23 #include "client_internal.h"
24
25 /************************** Private Message Send ****************************/
26
27 /* Sends private message to remote client. */
28
29 SilcBool silc_client_send_private_message(SilcClient client,
30                                           SilcClientConnection conn,
31                                           SilcClientEntry client_entry,
32                                           SilcMessageFlags flags,
33                                           SilcHash hash,
34                                           unsigned char *data,
35                                           SilcUInt32 data_len)
36 {
37   SilcBuffer buffer;
38   SilcBool ret;
39   SilcID sid, rid;
40
41   if (silc_unlikely(!client || !conn || !client_entry))
42     return FALSE;
43   if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash))
44     return FALSE;
45   if (silc_unlikely(conn->internal->disconnected))
46     return FALSE;
47
48   SILC_LOG_DEBUG(("Sending private message"));
49
50   /* Auto-negotiate private message key (AKE) if there is no key or
51      it's time to rekey. */
52   if (!client->internal->params->dont_autoneg_prvmsg_keys &&
53       !client_entry->internal.no_ake && client_entry != conn->local_entry &&
54       (!client_entry->internal.send_key ||
55        (client_entry->internal.ake_rekey <= silc_time() ||
56         client_entry->internal.ake_generation !=
57         conn->internal->ake_generation))) {
58     return silc_client_autoneg_private_message_key(
59                                         client, conn, client_entry, NULL,
60                                         flags, hash, data, data_len);
61   }
62
63   sid.type = SILC_ID_CLIENT;
64   sid.u.client_id = *conn->local_id;
65   rid.type = SILC_ID_CLIENT;
66   rid.u.client_id = client_entry->id;
67
68   /* Encode private message payload */
69   buffer =
70     silc_message_payload_encode(flags, data, data_len,
71                                 (!client_entry->internal.send_key ? FALSE :
72                                  !client_entry->internal.generated),
73                                 TRUE, client_entry->internal.send_key,
74                                 client_entry->internal.hmac_send,
75                                 client->rng, NULL, conn->private_key,
76                                 hash, &sid, &rid, NULL);
77   if (silc_unlikely(!buffer)) {
78     SILC_LOG_ERROR(("Error encoding private message"));
79     return FALSE;
80   }
81
82   /* Send the private message packet */
83   ret = silc_packet_send_ext(conn->stream, SILC_PACKET_PRIVATE_MESSAGE,
84                              client_entry->internal.send_key ?
85                              SILC_PACKET_FLAG_PRIVMSG_KEY : 0,
86                              0, NULL, SILC_ID_CLIENT, &client_entry->id,
87                              silc_buffer_datalen(buffer), NULL, NULL);
88
89   silc_buffer_free(buffer);
90   return ret;
91 }
92
93 /************************* Private Message Receive **************************/
94
95 /* Client resolving callback.  Continues with the private message processing */
96
97 static void silc_client_private_message_resolved(SilcClient client,
98                                                  SilcClientConnection conn,
99                                                  SilcStatus status,
100                                                  SilcDList clients,
101                                                  void *context)
102 {
103   /* If no client found, ignore the private message, a silent error */
104   if (!clients)
105     silc_fsm_next(context, silc_client_private_message_error);
106
107   /* Continue processing the private message packet */
108   SILC_FSM_CALL_CONTINUE(context);
109 }
110
111 /* Private message received. */
112
113 SILC_FSM_STATE(silc_client_private_message)
114 {
115   SilcClientConnection conn = fsm_context;
116   SilcClient client = conn->client;
117   SilcPacket packet = state_context;
118   SilcMessagePayload payload = NULL;
119   SilcClientID remote_id;
120   SilcClientEntry remote_client = NULL;
121   SilcMessageFlags flags;
122   unsigned char *message;
123   SilcUInt32 message_len;
124
125   SILC_LOG_DEBUG(("Received private message"));
126
127   if (silc_unlikely(packet->src_id_type != SILC_ID_CLIENT)) {
128     /** Invalid packet */
129     silc_fsm_next(fsm, silc_client_private_message_error);
130     return SILC_FSM_CONTINUE;
131   }
132
133   if (silc_unlikely(!silc_id_str2id(packet->src_id, packet->src_id_len,
134                                     SILC_ID_CLIENT, &remote_id,
135                                     sizeof(remote_id)))) {
136     /** Invalid source ID */
137     silc_fsm_next(fsm, silc_client_private_message_error);
138     return SILC_FSM_CONTINUE;
139   }
140
141   /* Check whether we know this client already */
142   remote_client = silc_client_get_client_by_id(client, conn, &remote_id);
143   if (!remote_client || !remote_client->nickname[0]) {
144     /** Resolve client info */
145     silc_client_unref_client(client, conn, remote_client);
146     SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
147                                          client, conn, &remote_id, NULL,
148                                          silc_client_private_message_resolved,
149                                          fsm));
150     /* NOT REACHED */
151   }
152
153   if (silc_unlikely(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY &&
154                     !remote_client->internal.receive_key &&
155                     !remote_client->internal.hmac_receive)) {
156 #if 1
157     /* Kludge to check if the message has SKE packet inside, and then start
158        key exchange protocol.  Remove this once AKE support is everywhere. */
159     payload = silc_message_payload_parse(silc_buffer_datalen(&packet->buffer),
160                                          TRUE, FALSE, NULL, NULL,
161                                          packet->src_id, packet->src_id_len,
162                                          packet->dst_id, packet->dst_id_len,
163                                          NULL, FALSE, NULL);
164     if (!payload)
165       goto out;
166
167     flags = silc_message_get_flags(payload);
168     if (flags & SILC_MESSAGE_FLAG_PACKET &&
169         silc_client_autoneg_private_message_key(client, conn, remote_client,
170                                                 packet, 0, NULL, NULL, 0))
171       packet = NULL;
172 #endif /* 0 */
173     goto out;
174   }
175
176   /* Parse the payload and decrypt it also if private message key is set */
177   payload =
178     silc_message_payload_parse(silc_buffer_datalen(&packet->buffer),
179                                TRUE, !remote_client->internal.generated,
180                                remote_client->internal.receive_key,
181                                remote_client->internal.hmac_receive,
182                                packet->src_id, packet->src_id_len,
183                                packet->dst_id, packet->dst_id_len,
184                                NULL, FALSE, NULL);
185   if (silc_unlikely(!payload)) {
186     /* Private message key is set but the sender may have removed it,
187        try to parse without it. */
188     if (remote_client->internal.receive_key) {
189       SILC_LOG_DEBUG(("Parse payload without using private message key"));
190       payload =
191         silc_message_payload_parse(silc_buffer_datalen(&packet->buffer),
192                                    TRUE, FALSE, NULL, NULL,
193                                    packet->src_id, packet->src_id_len,
194                                    packet->dst_id, packet->dst_id_len,
195                                    NULL, FALSE, NULL);
196     }
197   }
198   if (!payload)
199     goto out;
200
201   flags = silc_message_get_flags(payload);
202
203   /* If message contains SILC packet, process the packet here */
204   if (flags & SILC_MESSAGE_FLAG_PACKET) {
205     if (silc_client_autoneg_private_message_key(client, conn, remote_client,
206                                                 packet, 0, NULL, NULL, 0))
207       packet = NULL;
208     goto out;
209   }
210
211   message = silc_message_get_data(payload, &message_len);
212
213   /* Pass the private message to application */
214   client->internal->ops->private_message(client, conn, remote_client, payload,
215                                          flags, message, message_len);
216
217   /* See if we are away (gone). If we are away we will reply to the
218      sender with the set away message. */
219   if (conn->internal->away_message &&
220       !(flags & SILC_MESSAGE_FLAG_NOREPLY)) {
221     /* If it's me, ignore */
222     if (SILC_ID_CLIENT_COMPARE(&remote_id, conn->local_id))
223       goto out;
224
225     /* Send the away message */
226     silc_client_send_private_message(client, conn, remote_client,
227                                      SILC_MESSAGE_FLAG_AUTOREPLY |
228                                      SILC_MESSAGE_FLAG_NOREPLY, NULL,
229                                      conn->internal->away_message,
230                                      strlen(conn->internal->away_message));
231   }
232
233  out:
234   /** Packet processed */
235   if (packet)
236     silc_packet_free(packet);
237   silc_client_unref_client(client, conn, remote_client);
238   if (payload)
239     silc_message_payload_free(payload);
240   return SILC_FSM_FINISH;
241 }
242
243 /* Private message error. */
244
245 SILC_FSM_STATE(silc_client_private_message_error)
246 {
247   SilcPacket packet = state_context;
248   silc_packet_free(packet);
249   return SILC_FSM_FINISH;
250 }
251
252 /* Initialize private message waiter for the `conn' connection. */
253
254 SilcBool silc_client_private_message_wait_init(SilcClient client,
255                                                SilcClientConnection conn,
256                                                SilcClientEntry client_entry)
257 {
258   SilcID id;
259
260   if (client_entry->internal.prv_waiter)
261     return TRUE;
262
263   /* We want SILC_PACKET_PRIVATE_MESSAGE packets from this source ID. */
264   id.type = SILC_ID_CLIENT;
265   id.u.client_id = client_entry->id;
266
267   client_entry->internal.prv_waiter =
268     silc_packet_wait_init(conn->stream, &id, SILC_PACKET_PRIVATE_MESSAGE, -1);
269   if (!client_entry->internal.prv_waiter)
270     return FALSE;
271
272   return TRUE;
273 }
274
275 /* Uninitializes private message waiter. */
276
277 void silc_client_private_message_wait_uninit(SilcClient client,
278                                              SilcClientConnection conn,
279                                              SilcClientEntry client_entry)
280 {
281   if (!client_entry->internal.prv_waiter)
282     return;
283   silc_packet_wait_uninit(client_entry->internal.prv_waiter, conn->stream);
284   client_entry->internal.prv_waiter = NULL;
285 }
286
287 /* Blocks the calling process or thread until private message has been
288    received from the specified client. */
289
290 SilcBool silc_client_private_message_wait(SilcClient client,
291                                           SilcClientConnection conn,
292                                           SilcClientEntry client_entry,
293                                           SilcMessagePayload *payload)
294 {
295   SilcPacket packet;
296
297   if (!client_entry->internal.prv_waiter)
298     return FALSE;
299
300   /* Block until private message arrives */
301   do {
302     if ((silc_packet_wait(client_entry->internal.prv_waiter, 0, &packet)) < 0)
303       return FALSE;
304
305     /* Parse the payload and decrypt it also if private message key is set */
306     *payload =
307       silc_message_payload_parse(silc_buffer_data(&packet->buffer),
308                                  silc_buffer_len(&packet->buffer),
309                                  TRUE, !client_entry->internal.generated,
310                                  client_entry->internal.receive_key,
311                                  client_entry->internal.hmac_receive,
312                                  packet->src_id, packet->src_id_len,
313                                  packet->dst_id, packet->dst_id_len,
314                                  NULL, FALSE, NULL);
315     if (!(*payload)) {
316       silc_packet_free(packet);
317       continue;
318     }
319
320     break;
321   } while (1);
322
323   silc_packet_free(packet);
324   return TRUE;
325 }
326
327 /*************************** Private Message Key ****************************/
328
329 /* Sends private message key request.  Sender of this packet is initiator
330    when setting the private message key. */
331
332 static SilcBool
333 silc_client_send_private_message_key_request(SilcClient client,
334                                              SilcClientConnection conn,
335                                              SilcClientEntry client_entry)
336 {
337   const char *cipher, *hmac;
338
339   SILC_LOG_DEBUG(("Sending private message key request"));
340
341   cipher = silc_cipher_get_name(client_entry->internal.send_key);
342   hmac = silc_hmac_get_name(client_entry->internal.hmac_send);
343
344   /* Send the packet */
345   return silc_packet_send_va_ext(conn->stream,
346                                  SILC_PACKET_PRIVATE_MESSAGE_KEY,
347                                  0, 0, NULL, SILC_ID_CLIENT,
348                                  &client_entry->id, NULL, NULL,
349                                  SILC_STR_UI_SHORT(strlen(cipher)),
350                                  SILC_STR_DATA(cipher, strlen(cipher)),
351                                  SILC_STR_UI_SHORT(strlen(hmac)),
352                                  SILC_STR_DATA(hmac, strlen(hmac)),
353                                  SILC_STR_END);
354 }
355
356 /* Client resolving callback.  Here we simply mark that we are the responder
357    side of this private message key request.  */
358
359 static void silc_client_private_message_key_cb(SilcClient client,
360                                                SilcClientConnection conn,
361                                                SilcStatus status,
362                                                SilcDList clients,
363                                                void *context)
364 {
365   SilcFSMThread thread = context;
366   SilcPacket packet = silc_fsm_get_state_context(thread);
367   unsigned char *cipher = NULL, *hmac = NULL;
368   SilcClientEntry client_entry;
369   int ret;
370
371   if (!clients) {
372     silc_packet_free(packet);
373     silc_fsm_finish(thread);
374     return;
375   }
376
377   /* Parse the private message key payload */
378   ret = silc_buffer_unformat(&packet->buffer,
379                              SILC_STR_UI16_STRING_ALLOC(&cipher),
380                              SILC_STR_UI16_STRING_ALLOC(&hmac),
381                              SILC_STR_END);
382   if (!ret)
383     goto out;
384
385   /* Mark that we are responder */
386   client_entry = silc_dlist_get(clients);
387   if (client_entry)
388     client_entry->internal.prv_resp = TRUE;
389
390   /* XXX we should notify application that remote wants to set up the
391      static key.  And we should tell if we already have key with remote.
392      Application should return status telling whether to delete the key
393      or not. */
394
395  out:
396   silc_free(cipher);
397   silc_free(hmac);
398   silc_packet_free(packet);
399   silc_fsm_finish(thread);
400 }
401
402 /* Processes incoming Private Message Key payload to indicate that the
403    sender whishes to set up a static private message key. */
404
405 SILC_FSM_STATE(silc_client_private_message_key)
406 {
407   SilcClientConnection conn = fsm_context;
408   SilcClient client = conn->client;
409   SilcPacket packet = state_context;
410   SilcClientID remote_id;
411
412   if (packet->src_id_type != SILC_ID_CLIENT) {
413     silc_packet_free(packet);
414     return SILC_FSM_FINISH;
415   }
416
417   if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
418                       &remote_id, sizeof(remote_id))) {
419     silc_packet_free(packet);
420     return SILC_FSM_FINISH;
421   }
422
423   /* Always resolve the remote client.  The actual packet is processed
424      in the resolving callback. */
425   SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
426                                        client, conn, &remote_id, NULL,
427                                        silc_client_private_message_key_cb,
428                                        fsm));
429 }
430
431 /* Adds new private message key to `client_entry'.  If we are setting this
432    before receiving request for it from `client_entry' we will send the
433    request to the client.  Otherwise, we are responder side. */
434
435 SilcBool silc_client_add_private_message_key(SilcClient client,
436                                              SilcClientConnection conn,
437                                              SilcClientEntry client_entry,
438                                              const char *cipher,
439                                              const char *hmac,
440                                              unsigned char *key,
441                                              SilcUInt32 key_len)
442 {
443   SilcSKEKeyMaterial keymat;
444   SilcBool ret;
445
446   if (!client || !client_entry)
447     return FALSE;
448
449   /* Return FALSE if key already set */
450   if (client_entry->internal.send_key && client_entry->internal.receive_key)
451     return FALSE;
452
453   if (!cipher)
454     cipher = SILC_DEFAULT_CIPHER;
455   if (!hmac)
456     hmac = SILC_DEFAULT_HMAC;
457
458   /* Check the requested cipher and HMAC */
459   if (!silc_cipher_is_supported(cipher))
460     return FALSE;
461   if (!silc_hmac_is_supported(hmac))
462     return FALSE;
463
464   /* Save the key */
465   client_entry->internal.key = silc_memdup(key, key_len);
466   client_entry->internal.key_len = key_len;
467
468   /* Produce the key material as the protocol defines */
469   keymat = silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
470                                               conn->internal->sha1hash);
471   if (!keymat)
472     return FALSE;
473
474   /* Set the key into use */
475   ret = silc_client_add_private_message_key_ske(client, conn, client_entry,
476                                                 cipher, hmac, keymat);
477   client_entry->internal.generated = FALSE;
478
479   /* Free the key material */
480   silc_ske_free_key_material(keymat);
481
482   /* If we are setting the key without a request from the remote client,
483      we will send request to remote. */
484   if (!client_entry->internal.prv_resp)
485     silc_client_send_private_message_key_request(client, conn, client_entry);
486
487   return ret;
488 }
489
490 /* Same as above but takes the key material from the SKE key material
491    structure. */
492
493 SilcBool silc_client_add_private_message_key_ske(SilcClient client,
494                                                  SilcClientConnection conn,
495                                                  SilcClientEntry client_entry,
496                                                  const char *cipher,
497                                                  const char *hmac,
498                                                  SilcSKEKeyMaterial keymat)
499 {
500   if (!client || !client_entry)
501     return FALSE;
502
503   /* Return FALSE if key already set */
504   if (client_entry->internal.send_key && client_entry->internal.receive_key)
505     return FALSE;
506
507   if (!cipher)
508     cipher = SILC_DEFAULT_CIPHER;
509   if (!hmac)
510     hmac = SILC_DEFAULT_HMAC;
511
512   /* Check the requested cipher and HMAC */
513   if (!silc_cipher_is_supported(cipher))
514     return FALSE;
515   if (!silc_hmac_is_supported(hmac))
516     return FALSE;
517
518   client_entry->internal.generated = TRUE;
519   client_entry->internal.no_ake = TRUE;
520
521   /* Allocate the cipher and HMAC */
522   if (!silc_cipher_alloc(cipher, &client_entry->internal.send_key))
523     return FALSE;
524   if (!silc_cipher_alloc(cipher, &client_entry->internal.receive_key))
525     return FALSE;
526   if (!silc_hmac_alloc(hmac, NULL, &client_entry->internal.hmac_send))
527     return FALSE;
528   if (!silc_hmac_alloc(hmac, NULL, &client_entry->internal.hmac_receive))
529     return FALSE;
530
531   /* Set the keys */
532   if (client_entry->internal.prv_resp) {
533     silc_cipher_set_key(client_entry->internal.send_key,
534                         keymat->receive_enc_key,
535                         keymat->enc_key_len, TRUE);
536     silc_cipher_set_iv(client_entry->internal.send_key,
537                        keymat->receive_iv);
538     silc_cipher_set_key(client_entry->internal.receive_key,
539                         keymat->send_enc_key,
540                         keymat->enc_key_len, FALSE);
541     silc_cipher_set_iv(client_entry->internal.receive_key, keymat->send_iv);
542     silc_hmac_set_key(client_entry->internal.hmac_send,
543                       keymat->receive_hmac_key,
544                       keymat->hmac_key_len);
545     silc_hmac_set_key(client_entry->internal.hmac_receive,
546                       keymat->send_hmac_key,
547                       keymat->hmac_key_len);
548   } else {
549     silc_cipher_set_key(client_entry->internal.send_key,
550                         keymat->send_enc_key,
551                         keymat->enc_key_len, TRUE);
552     silc_cipher_set_iv(client_entry->internal.send_key,
553                        keymat->send_iv);
554     silc_cipher_set_key(client_entry->internal.receive_key,
555                         keymat->receive_enc_key,
556                         keymat->enc_key_len, FALSE);
557     silc_cipher_set_iv(client_entry->internal.receive_key, keymat->receive_iv);
558     silc_hmac_set_key(client_entry->internal.hmac_send,
559                       keymat->send_hmac_key,
560                       keymat->hmac_key_len);
561     silc_hmac_set_key(client_entry->internal.hmac_receive,
562                       keymat->receive_hmac_key,
563                       keymat->hmac_key_len);
564   }
565
566   return TRUE;
567 }
568
569 /* Removes the private message from the library. The key won't be used
570    after this to protect the private messages with the remote `client_entry'
571    client. Returns FALSE on error, TRUE otherwise. */
572
573 SilcBool silc_client_del_private_message_key(SilcClient client,
574                                              SilcClientConnection conn,
575                                              SilcClientEntry client_entry)
576 {
577   if (!client || !client_entry)
578     return FALSE;
579
580   if (!client_entry->internal.send_key && !client_entry->internal.receive_key)
581     return FALSE;
582
583   silc_cipher_free(client_entry->internal.send_key);
584   silc_cipher_free(client_entry->internal.receive_key);
585
586   if (client_entry->internal.key) {
587     memset(client_entry->internal.key, 0, client_entry->internal.key_len);
588     silc_free(client_entry->internal.key);
589   }
590
591   client_entry->internal.send_key = NULL;
592   client_entry->internal.receive_key = NULL;
593   client_entry->internal.key = NULL;
594   client_entry->internal.prv_resp = FALSE;
595
596   return TRUE;
597 }
598
599 /* Returns array of set private message keys associated to the connection
600    `conn'. Returns allocated SilcPrivateMessageKeys array and the array
601    count to the `key_count' argument. The array must be freed by the caller
602    by calling the silc_client_free_private_message_keys function. Note:
603    the keys returned in the array is in raw format. It might not be desired
604    to show the keys as is. The application might choose not to show the keys
605    at all or to show the fingerprints of the keys. */
606
607 SilcPrivateMessageKeys
608 silc_client_list_private_message_keys(SilcClient client,
609                                       SilcClientConnection conn,
610                                       SilcUInt32 *key_count)
611 {
612   SilcPrivateMessageKeys keys;
613   SilcUInt32 count = 0;
614   SilcList list;
615   SilcIDCacheEntry id_cache;
616   SilcClientEntry entry;
617
618   if (!client || !conn)
619     return NULL;
620
621   silc_mutex_lock(conn->internal->lock);
622   if (!silc_idcache_get_all(conn->internal->client_cache, &list)) {
623     silc_mutex_unlock(conn->internal->lock);
624     return NULL;
625   }
626
627   keys = silc_calloc(silc_list_count(list), sizeof(*keys));
628   if (!keys) {
629     silc_mutex_unlock(conn->internal->lock);
630     return NULL;
631   }
632
633   silc_list_start(list);
634   while ((id_cache = silc_list_get(list))) {
635     entry = id_cache->context;
636     if (entry->internal.send_key) {
637       keys[count].client_entry = entry;
638       keys[count].cipher = (char *)silc_cipher_get_name(entry->internal.
639                                                         send_key);
640       keys[count].key = (entry->internal.generated == FALSE ?
641                          entry->internal.key : NULL);
642       keys[count].key_len = (entry->internal.generated == FALSE ?
643                              entry->internal.key_len : 0);
644       count++;
645     }
646   }
647
648   silc_mutex_unlock(conn->internal->lock);
649
650   if (key_count)
651     *key_count = count;
652
653   return keys;
654 }
655
656 /* Frees the SilcPrivateMessageKeys array returned by the function
657    silc_client_list_private_message_keys. */
658
659 void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
660                                            SilcUInt32 key_count)
661 {
662   silc_free(keys);
663 }
664
665 /* Return private message key from the client entry. */
666
667 SilcBool
668 silc_client_private_message_key_is_set(SilcClient client,
669                                        SilcClientConnection conn,
670                                        SilcClientEntry client_entry)
671 {
672   return client_entry->internal.send_key != NULL;
673 }
674
675 /********************* Private Message Key Autoneg (AKE) ********************/
676
677 /* Private message key auto-negotiation context */
678 struct SilcClientAutonegMessageKeyStruct {
679   SilcClientConnection conn;             /* Connection to server */
680   SilcSKE ske;                           /* SKE with remote client */
681   SilcAsyncOperation ske_op;             /* SKE operation */
682   SilcStream stream;                     /* PRIVATE_MESSAGE stream */
683   SilcPacketStream ske_stream;           /* Packet stream for SKE (inside
684                                             the PRIVATE_MESSAGE stream) */
685   SilcDList messages;                    /* Message queue */
686   SilcHash hash;                         /* Initial message hash */
687   SilcPublicKey public_key;              /* Remote client public key */
688   SilcVerifyKeyContext verify;
689   SilcSKEParamsStruct params;
690   SilcUInt32 generation;                 /* Starting AKE generation */
691 };
692
693 static SilcBool
694 silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,
695                                  SilcPacketStream stream,
696                                  SilcPacket packet,
697                                  void *callback_context,
698                                  void *stream_context);
699
700 static const SilcPacketCallbacks autoneg_key_ske_cbs =
701 {
702   silc_client_autoneg_key_recv_ske, NULL, NULL
703 };
704
705 /* Destroy auto-negotiation context */
706
707 static void silc_client_autoneg_key_free(SilcClient client,
708                                          SilcClientConnection conn,
709                                          SilcClientEntry client_entry)
710 {
711   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
712   SilcBuffer m;
713
714   if (ake->ske_op)
715     silc_async_abort(ake->ske_op, NULL, NULL);
716
717   silc_ske_free(ake->ske);
718   silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
719   silc_packet_stream_destroy(ake->ske_stream);
720   if (ake->hash)
721     silc_hash_free(ake->hash);
722
723   silc_dlist_start(ake->messages);
724   while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
725     silc_dlist_del(ake->messages, m);
726     silc_buffer_free(m);
727   }
728   silc_dlist_uninit(ake->messages);
729
730   client_entry->internal.op = NULL;
731   client_entry->internal.ake = NULL;
732   silc_client_unref_client(client, conn, client_entry);
733
734   if (ake->verify)
735     ake->verify->aborted = TRUE;
736   else if (ake->public_key)
737     silc_pkcs_public_key_free(ake->public_key);
738
739   silc_free(ake);
740 }
741
742 /* Destroy auto-negotiation context */
743
744 SILC_TASK_CALLBACK(silc_client_autoneg_key_finish)
745 {
746   SilcClientEntry client_entry = context;
747   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
748   SilcClientConnection conn = ake->conn;
749   SilcClient client = conn->client;
750
751   silc_client_autoneg_key_free(client, conn, client_entry);
752 }
753
754 /* Abort callback.  This aborts the auto-negotiation and the SKE */
755
756 static void
757 silc_client_autoneg_key_abort(SilcAsyncOperation op, void *context)
758 {
759   SilcClientEntry client_entry = context;
760   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
761   SilcClientConnection conn = ake->conn;
762   SilcClient client = conn->client;
763
764   if (!ake)
765     return;
766
767   silc_client_autoneg_key_free(client, conn, client_entry);
768 }
769
770 /* SKE packet stream callback.  Here we verify that the packets we got
771    from the private message are actually SKE packets for us. */
772
773 static SilcBool
774 silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,
775                                  SilcPacketStream stream,
776                                  SilcPacket packet,
777                                  void *callback_context,
778                                  void *stream_context)
779 {
780   SilcClientEntry client_entry = stream_context;
781   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
782   SilcClientID remote_id;
783
784   SILC_LOG_DEBUG(("Packet %p type %d inside private message", packet,
785                   packet->type));
786
787   /* Take only SKE packets, drop others, no support for anything else */
788   if (packet->type != SILC_PACKET_KEY_EXCHANGE &&
789       packet->type != SILC_PACKET_KEY_EXCHANGE_1 &&
790       packet->type != SILC_PACKET_KEY_EXCHANGE_2 &&
791       packet->type != SILC_PACKET_FAILURE)
792     goto drop;
793
794   /* Must be from client to client */
795   if (packet->dst_id_type != SILC_ID_CLIENT ||
796       packet->src_id_type != SILC_ID_CLIENT)
797     goto drop;
798
799   if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
800                       &remote_id, sizeof(remote_id)))
801     goto drop;
802
803   if (!SILC_ID_CLIENT_COMPARE(&client_entry->id, &remote_id)) {
804     /* The packet is not for this client, but it must be */
805     SILC_LOG_DEBUG(("Client ids do not match"));
806     goto drop;
807   }
808
809   /* Responder is started here if correct packet comes in */
810   if (!ake->ske_op) {
811     if (packet->type == SILC_PACKET_KEY_EXCHANGE) {
812       /* Ignore pre-set proposal */
813       if (ake->params.prop) {
814         silc_ske_group_free(ake->params.prop->group);
815         silc_cipher_free(ake->params.prop->cipher);
816         silc_hash_free(ake->params.prop->hash);
817         silc_hmac_free(ake->params.prop->hmac);
818         silc_pkcs_public_key_free(ake->params.prop->public_key);
819         silc_free(ake->params.prop);
820         ake->params.prop = NULL;
821       }
822     } else if (packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
823       SILC_LOG_DEBUG(("Invalid SKE packet for responder"));
824       silc_async_abort(client_entry->internal.op, NULL, NULL);
825       goto drop;
826     }
827
828     ake->ske_op = silc_ske_responder(ake->ske, ake->ske_stream, &ake->params);
829     if (!ake->ske_op) {
830       silc_async_abort(client_entry->internal.op, NULL, NULL);
831       goto drop;
832     }
833
834     /* We have to re-inject the packet to SKE stream because SKE wasn't
835        listenning to these packets until silc_ske_responder() was called */
836     silc_packet_stream_inject(ake->ske_stream, packet);
837     return TRUE;
838   }
839
840   /* Packet is ok and is for us, let it pass to SKE */
841   SILC_LOG_DEBUG(("Pass packet %p type %d", packet, packet->type));
842   return FALSE;
843
844  drop:
845   silc_packet_free(packet);
846   return TRUE;
847 }
848
849 /* Coder callback for actually encoding/decoding the SKE packets inside
850    private messages. */
851
852 static SilcBool silc_client_autoneg_key_coder(SilcStream stream,
853                                               SilcStreamStatus status,
854                                               SilcBuffer buffer,
855                                               void *context)
856 {
857   SilcBool ret = FALSE;
858   SilcBuffer message;
859   SilcMessagePayload payload = NULL;
860   SilcMessageFlags flags;
861   unsigned char *msg;
862   SilcUInt32 message_len;
863
864   switch (status) {
865   case SILC_STREAM_CAN_READ:
866     /* Decode private message.  We get all private messages here from
867        the remote client while we're doing SKE, so we must take the
868        correct messages. */
869     SILC_LOG_DEBUG(("Decode packet inside private message"));
870
871     payload = silc_message_payload_parse(silc_buffer_datalen(buffer),
872                                          TRUE, FALSE, NULL, NULL, NULL, 0,
873                                          NULL, 0, NULL, FALSE, NULL);
874     if (!payload) {
875       SILC_LOG_DEBUG(("Error decoding private message payload"));
876       goto out;
877     }
878
879     /* Ignore this message if it's not packet */
880     flags = silc_message_get_flags(payload);
881     if (!(flags & SILC_MESSAGE_FLAG_PACKET)) {
882       SILC_LOG_DEBUG(("Private message doesn't contain packet"));
883       silc_message_payload_free(payload);
884       goto out;
885     }
886
887     /* Take the packet */
888     ret = TRUE;
889
890     msg = silc_message_get_data(payload, &message_len);
891     silc_buffer_reset(buffer);
892     if (!silc_buffer_enlarge(buffer, message_len)) {
893       silc_message_payload_free(payload);
894       goto out;
895     }
896     silc_buffer_put(buffer, msg, message_len);
897
898     silc_message_payload_free(payload);
899     break;
900
901   case SILC_STREAM_CAN_WRITE:
902     /* Encode private message */
903     SILC_LOG_DEBUG(("Encode packet inside private message"));
904
905     ret = TRUE;
906
907     message =
908       silc_message_payload_encode(SILC_MESSAGE_FLAG_PACKET,
909                                   silc_buffer_datalen(buffer),
910                                   FALSE, TRUE, NULL, NULL, NULL,
911                                   NULL, NULL, NULL, NULL, NULL, NULL);
912     if (!message) {
913       SILC_LOG_DEBUG(("Error encoding private message payload"));
914       goto out;
915     }
916
917     silc_buffer_reset(buffer);
918     if (!silc_buffer_enlarge(buffer, silc_buffer_len(message)))
919       goto out;
920     silc_buffer_put(buffer, silc_buffer_datalen(message));
921
922     break;
923
924   default:
925     break;
926   }
927
928  out:
929   return ret;
930 }
931
932 /* Called after application has verified remote client's public key */
933
934 static void
935 silc_client_autoneg_key_verify_pubkey_cb(SilcBool success, void *context)
936 {
937   SilcVerifyKeyContext verify = context;
938   SilcClientAutonegMessageKey ake = verify->context;
939
940   SILC_LOG_DEBUG(("Start, verify %p, ake %p", context, ake));
941
942   /* Call the completion callback back to the SKE */
943   if (!verify->aborted) {
944     ake->verify = NULL;
945     verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
946                        SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
947                        verify->completion_context);
948   } else {
949     silc_pkcs_public_key_free(verify->public_key);
950   }
951
952   silc_free(verify);
953 }
954
955 /* Remote client's public key verification callback */
956
957 static void
958 silc_client_autoneg_key_verify_pubkey(SilcSKE ske,
959                                       SilcPublicKey public_key,
960                                       void *context,
961                                       SilcSKEVerifyCbCompletion completion,
962                                       void *completion_context)
963 {
964   SilcClientEntry client_entry = context;
965   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
966   SilcClientConnection conn = ake->conn;
967   SilcClient client = conn->client;
968   SilcVerifyKeyContext verify;
969
970   /* Use public key we cached earlier in AKE for direction verification */
971   if (client_entry->internal.send_key && client_entry->public_key &&
972       silc_pkcs_public_key_compare(public_key, client_entry->public_key)) {
973     SILC_LOG_DEBUG(("Client's cached public key matches"));
974     completion(ske, SILC_SKE_STATUS_OK, completion_context);
975     return;
976   }
977
978   /* If we provided repository for SKE and we got here the key was not
979      found from the repository. */
980   if (conn->internal->params.repository &&
981       !conn->internal->params.verify_notfound) {
982     completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
983                completion_context);
984     return;
985   }
986
987   SILC_LOG_DEBUG(("Verify remote client public key"));
988
989   ake->public_key = silc_pkcs_public_key_copy(public_key);
990   if (!ake->public_key) {
991     completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
992                completion_context);
993     return;
994   }
995
996   verify = silc_calloc(1, sizeof(*verify));
997   if (!verify) {
998     completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
999                completion_context);
1000     return;
1001   }
1002   verify->public_key = ake->public_key;
1003   verify->ske = ske;
1004   verify->completion = completion;
1005   verify->completion_context = completion_context;
1006   verify->context = ake;
1007   ake->verify = verify;
1008
1009   /* Verify public key in application */
1010   client->internal->ops->verify_public_key(
1011                                 client, conn,
1012                                 SILC_CONN_CLIENT, ake->public_key,
1013                                 silc_client_autoneg_key_verify_pubkey_cb,
1014                                 verify);
1015 }
1016
1017 /* Key exchange protocol completion callback */
1018
1019 static void silc_client_autoneg_key_done(SilcSKE ske,
1020                                          SilcSKEStatus status,
1021                                          SilcSKESecurityProperties prop,
1022                                          SilcSKEKeyMaterial keymat,
1023                                          SilcSKERekeyMaterial rekey,
1024                                          void *context)
1025 {
1026   SilcClientEntry client_entry = context;
1027   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
1028   SilcClientConnection conn = ake->conn;
1029   SilcClient client = conn->client;
1030   SilcBool initiator = !client_entry->internal.prv_resp;
1031   SilcMessageFlags flags;
1032   SilcBuffer m;
1033
1034   ake->ske_op = NULL;
1035
1036   conn->context_type = SILC_ID_CLIENT;
1037   conn->client_entry = client_entry;
1038
1039   if (status != SILC_SKE_STATUS_OK) {
1040     /* Key exchange failed */
1041     SILC_LOG_DEBUG(("Error during key exchange: %s (%d)",
1042                     silc_ske_map_status(status), status));
1043
1044     if (initiator) {
1045       if (status != SILC_SKE_STATUS_PROBE_TIMEOUT)
1046         client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1047                                    "Cannot send private message to %s (%s)",
1048                                    client_entry->nickname,
1049                                    silc_ske_map_status(status));
1050       else if (client_entry->mode & SILC_UMODE_DETACHED)
1051         client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1052                                    "Cannot send private message to detached "
1053                                    "client %s", client_entry->nickname);
1054     } else if (status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
1055       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1056                                  "Private message key exchange failed "
1057                                  "with %s (%s)", client_entry->nickname,
1058                                  silc_ske_map_status(status));
1059     }
1060
1061     /* Errors that occur due to user not responding or deciding not to
1062        trust the public key will not cause us to stop trying AKE next time.
1063        Other errors disable AKE to allow communication with other means. */
1064     if (initiator && status != SILC_SKE_STATUS_TIMEOUT &&
1065         status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY &&
1066         !(client_entry->mode & SILC_UMODE_DETACHED)) {
1067       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
1068                                  "Cannot auto-negotiate key with %s, "
1069                                  "messages will be protected with "
1070                                  "session key", client_entry->nickname);
1071
1072       /* Don't try this again with this client */
1073       client_entry->internal.no_ake = TRUE;
1074     }
1075     goto out;
1076   }
1077
1078   /* Set the new private message key into use */
1079   silc_client_del_private_message_key(client, conn, client_entry);
1080   client_entry->internal.prv_resp = !initiator;
1081   if (!silc_client_add_private_message_key_ske(
1082                                         client, conn, client_entry,
1083                                         silc_cipher_get_name(prop->cipher),
1084                                         silc_hmac_get_name(prop->hmac),
1085                                         keymat)) {
1086     SILC_LOG_DEBUG(("Error adding private message key"));
1087
1088     client->internal->ops->say(client, conn,
1089                                SILC_CLIENT_MESSAGE_ERROR,
1090                                "Private message key exchange error: "
1091                                "cannot use keys");
1092
1093     /* Don't try this again with this client */
1094     client_entry->internal.no_ake = TRUE;
1095     goto out;
1096   }
1097
1098   /* Save the public key to client entry */
1099   if (!client_entry->public_key) {
1100     client_entry->public_key = ake->public_key;
1101     ake->public_key = NULL;
1102   }
1103
1104   /* Rekey periodically */
1105   client_entry->internal.ake_rekey = silc_time() + 300;
1106   if (initiator)
1107     client_entry->internal.ake_rekey -= 30;
1108   client_entry->internal.ake_generation = conn->internal->ake_generation;
1109   client_entry->internal.no_ake = FALSE;
1110
1111   SILC_LOG_DEBUG(("AKE completed as %s with %s, rekey in %u secs, "
1112                   "generation %u", initiator ? "initiator" : "responder",
1113                   client_entry->nickname, 300,
1114                   conn->internal->ake_generation));
1115
1116   /* Send queued messages */
1117   silc_dlist_start(ake->messages);
1118   while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
1119     SILC_GET16_MSB(flags, m->data - 2);
1120     silc_client_send_private_message(client, conn, client_entry,
1121                                      flags, ake->hash,
1122                                      silc_buffer_datalen(m));
1123   }
1124
1125  out:
1126   conn->context_type = SILC_ID_NONE;
1127   conn->client_entry = NULL;
1128   silc_schedule_task_add_timeout(client->schedule,
1129                                  silc_client_autoneg_key_finish,
1130                                  client_entry, 0, 1);
1131 }
1132
1133 /* Auto-negotiate private message key with the remote client using the
1134    SKE protocol, which is tunneled through the SILC network inside private
1135    messages shared between the us and the remote client.
1136
1137    This operation is naturally asynchronous and will involve exchanging
1138    multiple messages back and forth.  Despite this, we don't run this
1139    operation in own FSM thread here, but instead will use the SKE library
1140    to do the asynchronous operation which we can abort at any time in
1141    case user disconnects.
1142
1143    Messages and packets we receive during this operation will be processed
1144    in the normal connection thread. */
1145
1146 SilcBool
1147 silc_client_autoneg_private_message_key(SilcClient client,
1148                                         SilcClientConnection conn,
1149                                         SilcClientEntry client_entry,
1150                                         SilcPacket initiator_packet,
1151                                         SilcMessageFlags flags,
1152                                         SilcHash hash,
1153                                         unsigned char *data,
1154                                         SilcUInt32 data_len)
1155 {
1156   SilcClientAutonegMessageKey ake;
1157   SilcBool initiator = initiator_packet == NULL;
1158   SilcBuffer m;
1159
1160   SILC_LOG_DEBUG(("Start private message AKE as %s with %s",
1161                   initiator ? "initiator" : "responder",
1162                   client_entry->nickname));
1163
1164   if (client_entry->internal.op) {
1165     ake = client_entry->internal.ake;
1166     if (ake && data) {
1167       /* If generation has changed, we must abort this exchange and
1168          start a new one. */
1169       if (ake->generation != conn->internal->ake_generation) {
1170         SILC_LOG_DEBUG(("Abort ongoing AKE and start new one"));
1171         silc_async_abort(client_entry->internal.op, NULL, NULL);
1172       } else {
1173         SILC_LOG_DEBUG(("AKE is ongoing, queue the message"));
1174
1175         m = silc_buffer_alloc_size(data_len + 2);
1176         if (!m)
1177           return FALSE;
1178         SILC_PUT16_MSB(flags, m->data);
1179         silc_buffer_pull(m, 2);
1180         silc_buffer_put(m, data, data_len);
1181         silc_dlist_add(ake->messages, m);
1182         return TRUE;
1183       }
1184     } else {
1185       SILC_LOG_DEBUG(("Cannot start AKE, operation %p is ongoing",
1186                       client_entry->internal.op));
1187       return FALSE;
1188     }
1189   }
1190
1191   ake = silc_calloc(1, sizeof(*ake));
1192   if (!ake)
1193     return FALSE;
1194   ake->conn = conn;
1195   ake->generation = conn->internal->ake_generation;
1196
1197   ake->messages = silc_dlist_init();
1198   if (!ake->messages)
1199     goto err;
1200
1201   /* Wrap our packet stream to a generic stream for the private messages
1202      we are going to exchange.  We send the packets with packet flag
1203      SILC_PACKET_FLAG_PRIVMSG_KEY which is a lie, but is a way to get
1204      clients which do not support this protocol to ignore these messages.
1205      This kludge should be removed once support is everywhere and
1206      responder should look only for the SILC_MESSAGE_FLAG_PACKET. */
1207   ake->stream = silc_packet_stream_wrap(conn->stream,
1208                                         SILC_PACKET_PRIVATE_MESSAGE,
1209                                         SILC_PACKET_FLAG_PRIVMSG_KEY, FALSE,
1210                                         SILC_ID_NONE, NULL,
1211                                         SILC_ID_CLIENT, &client_entry->id,
1212                                         silc_client_autoneg_key_coder,
1213                                         client_entry);
1214   if (!ake->stream)
1215     goto err;
1216
1217   /* Create a new packet stream for the SKE library using the wrapped
1218      stream as the underlaying stream, in effect creating a tunnel to
1219      send SKE packets inside private message packets. */
1220   ake->ske_stream = silc_packet_stream_create(client->internal->packet_engine,
1221                                               conn->internal->schedule,
1222                                               ake->stream);
1223   if (!ake->ske_stream)
1224     goto err;
1225
1226   silc_packet_set_context(ake->ske_stream, client_entry);
1227   silc_packet_set_ids(ake->ske_stream, SILC_ID_CLIENT, conn->local_id,
1228                       SILC_ID_CLIENT, &client_entry->id);
1229
1230   /* Link to the new packet stream to intercept the packets before they
1231      go to SKE library so that we can do additional checks and decide if
1232      we really want to process the packets. */
1233   if (!silc_packet_stream_link(ake->ske_stream, &autoneg_key_ske_cbs, NULL,
1234                                1000001, SILC_PACKET_ANY, -1))
1235     goto err;
1236
1237   /* Create SKE */
1238   ake->ske = silc_ske_alloc(client->rng, conn->internal->schedule,
1239                             conn->internal->params.repository,
1240                             conn->public_key, conn->private_key,
1241                             client_entry);
1242   if (!ake->ske)
1243     goto err;
1244
1245   silc_ske_set_callbacks(ake->ske, silc_client_autoneg_key_verify_pubkey,
1246                          silc_client_autoneg_key_done, client_entry);
1247   ake->params.version = client->internal->silc_client_version;
1248   ake->params.probe_timeout_secs = 5;
1249   ake->params.timeout_secs = 120;
1250   ake->params.flags = SILC_SKE_SP_FLAG_MUTUAL | SILC_SKE_SP_FLAG_PFS;
1251   ake->params.small_proposal = TRUE;
1252   ake->params.no_acks = TRUE;
1253
1254   if (client_entry->internal.send_key &&
1255       client_entry->internal.ake_generation == ake->generation) {
1256     /* Security properties for rekey */
1257     SilcSKESecurityProperties prop = silc_calloc(1, sizeof(*prop));
1258     if (!prop)
1259       goto err;
1260     silc_cipher_alloc(silc_cipher_get_name(client_entry->internal.send_key),
1261                       &prop->cipher);
1262     silc_hmac_alloc(silc_hmac_get_name(client_entry->internal.hmac_send),
1263                     NULL, &prop->hmac);
1264     silc_hash_alloc(silc_hash_get_name(silc_hmac_get_hash(
1265                         client_entry->internal.hmac_send)), &prop->hash);
1266     prop->public_key = silc_pkcs_public_key_copy(client_entry->public_key);
1267     silc_ske_group_get_by_number(2, &prop->group);
1268     prop->flags = ake->params.flags;
1269     ake->params.prop = prop;
1270   }
1271
1272   /* Start key exchange, responder is started in the packet callback  */
1273   if (initiator) {
1274     ake->ske_op = silc_ske_initiator(ake->ske, ake->ske_stream, &ake->params,
1275                                      NULL);
1276     if (!ake->ske_op)
1277       goto err;
1278   }
1279
1280   /* Finally, set up the client entry */
1281   client_entry->internal.op = silc_async_alloc(silc_client_autoneg_key_abort,
1282                                                NULL, client_entry);
1283   if (!client_entry->internal.op)
1284     goto err;
1285   client_entry->internal.ake = ake;
1286   client_entry->internal.no_ake = FALSE;
1287   client_entry->internal.prv_resp = !initiator;
1288   silc_client_ref_client(client, conn, client_entry);
1289
1290   /* As responder reinject the packet to the new stream so it gets decoded
1291      from the private message payload. */
1292   if (initiator_packet)
1293     silc_packet_stream_inject(conn->stream, initiator_packet);
1294
1295   /* Save the initial message, it will be sent after the key has been
1296      negotiated. */
1297   if (data && data_len) {
1298     m = silc_buffer_alloc_size(data_len + 2);
1299     if (m) {
1300       SILC_PUT16_MSB(flags, m->data);
1301       silc_buffer_pull(m, 2);
1302       silc_buffer_put(m, data, data_len);
1303       silc_dlist_add(ake->messages, m);
1304     }
1305     if (hash)
1306       silc_hash_alloc(silc_hash_get_name(hash), &ake->hash);
1307   }
1308
1309   return TRUE;
1310
1311  err:
1312   if (ake->ske)
1313     silc_ske_free(ake->ske);
1314   if (ake->ske_stream) {
1315     silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
1316     silc_packet_stream_destroy(ake->ske_stream);
1317   } else if (ake->stream)
1318     silc_stream_destroy(ake->stream);
1319   silc_dlist_uninit(ake->messages);
1320   silc_free(ake);
1321   return FALSE;
1322 }
1323
1324 /* Sets away `message'.  The away message may be set when the client's
1325    mode is changed to SILC_UMODE_GONE and the client whishes to reply
1326    to anyone who sends private message.  The `message' will be sent
1327    automatically back to the the client who send private message.  If
1328    away message is already set this replaces the old message with the
1329    new one.  If `message' is NULL the old away message is removed.
1330    The sender may freely free the memory of the `message'. */
1331
1332 SilcBool silc_client_set_away_message(SilcClient client,
1333                                       SilcClientConnection conn,
1334                                       char *message)
1335 {
1336   if (!client || !conn)
1337     return FALSE;
1338
1339   if (!message) {
1340     silc_free(conn->internal->away_message);
1341     conn->internal->away_message = NULL;
1342     return TRUE;
1343   }
1344
1345   if (conn->internal->away_message)
1346     silc_free(conn->internal->away_message);
1347
1348   conn->internal->away_message = strdup(message);
1349   if (!conn->internal->away_message)
1350     return FALSE;
1351
1352   return TRUE;
1353 }