silcclient: associate context with verify_public_key
[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   conn->context_type = SILC_ID_CLIENT;
1010   conn->client_entry = client_entry;
1011
1012   /* Verify public key in application */
1013   client->internal->ops->verify_public_key(
1014                                 client, conn,
1015                                 SILC_CONN_CLIENT, ake->public_key,
1016                                 silc_client_autoneg_key_verify_pubkey_cb,
1017                                 verify);
1018
1019   conn->context_type = SILC_ID_NONE;
1020 }
1021
1022 /* Key exchange protocol completion callback */
1023
1024 static void silc_client_autoneg_key_done(SilcSKE ske,
1025                                          SilcSKEStatus status,
1026                                          SilcSKESecurityProperties prop,
1027                                          SilcSKEKeyMaterial keymat,
1028                                          SilcSKERekeyMaterial rekey,
1029                                          void *context)
1030 {
1031   SilcClientEntry client_entry = context;
1032   SilcClientAutonegMessageKey ake = client_entry->internal.ake;
1033   SilcClientConnection conn = ake->conn;
1034   SilcClient client = conn->client;
1035   SilcBool initiator = !client_entry->internal.prv_resp;
1036   SilcMessageFlags flags;
1037   SilcBuffer m;
1038
1039   ake->ske_op = NULL;
1040
1041   conn->context_type = SILC_ID_CLIENT;
1042   conn->client_entry = client_entry;
1043
1044   if (status != SILC_SKE_STATUS_OK) {
1045     /* Key exchange failed */
1046     SILC_LOG_DEBUG(("Error during key exchange: %s (%d)",
1047                     silc_ske_map_status(status), status));
1048
1049     if (initiator) {
1050       if (status != SILC_SKE_STATUS_PROBE_TIMEOUT)
1051         client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1052                                    "Cannot send private message to %s (%s)",
1053                                    client_entry->nickname,
1054                                    silc_ske_map_status(status));
1055       else if (client_entry->mode & SILC_UMODE_DETACHED)
1056         client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1057                                    "Cannot send private message to detached "
1058                                    "client %s", client_entry->nickname);
1059     } else if (status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
1060       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1061                                  "Private message key exchange failed "
1062                                  "with %s (%s)", client_entry->nickname,
1063                                  silc_ske_map_status(status));
1064     }
1065
1066     /* Errors that occur due to user not responding or deciding not to
1067        trust the public key will not cause us to stop trying AKE next time.
1068        Other errors disable AKE to allow communication with other means. */
1069     if (initiator && status != SILC_SKE_STATUS_TIMEOUT &&
1070         status != SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY &&
1071         !(client_entry->mode & SILC_UMODE_DETACHED)) {
1072       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
1073                                  "Cannot auto-negotiate key with %s, "
1074                                  "messages will be protected with "
1075                                  "session key", client_entry->nickname);
1076
1077       /* Don't try this again with this client */
1078       client_entry->internal.no_ake = TRUE;
1079     }
1080     goto out;
1081   }
1082
1083   /* Set the new private message key into use */
1084   silc_client_del_private_message_key(client, conn, client_entry);
1085   client_entry->internal.prv_resp = !initiator;
1086   if (!silc_client_add_private_message_key_ske(
1087                                         client, conn, client_entry,
1088                                         silc_cipher_get_name(prop->cipher),
1089                                         silc_hmac_get_name(prop->hmac),
1090                                         keymat)) {
1091     SILC_LOG_DEBUG(("Error adding private message key"));
1092
1093     client->internal->ops->say(client, conn,
1094                                SILC_CLIENT_MESSAGE_ERROR,
1095                                "Private message key exchange error: "
1096                                "cannot use keys");
1097
1098     /* Don't try this again with this client */
1099     client_entry->internal.no_ake = TRUE;
1100     goto out;
1101   }
1102
1103   /* Save the public key to client entry */
1104   if (!client_entry->public_key) {
1105     client_entry->public_key = ake->public_key;
1106     ake->public_key = NULL;
1107   }
1108
1109   /* Rekey periodically */
1110   client_entry->internal.ake_rekey = silc_time() + 300;
1111   if (initiator)
1112     client_entry->internal.ake_rekey -= 30;
1113   client_entry->internal.ake_generation = conn->internal->ake_generation;
1114   client_entry->internal.no_ake = FALSE;
1115
1116   SILC_LOG_DEBUG(("AKE completed as %s with %s, rekey in %u secs, "
1117                   "generation %u", initiator ? "initiator" : "responder",
1118                   client_entry->nickname, 300,
1119                   conn->internal->ake_generation));
1120
1121   /* Send queued messages */
1122   silc_dlist_start(ake->messages);
1123   while ((m = silc_dlist_get(ake->messages)) != SILC_LIST_END) {
1124     SILC_GET16_MSB(flags, m->data - 2);
1125     silc_client_send_private_message(client, conn, client_entry,
1126                                      flags, ake->hash,
1127                                      silc_buffer_datalen(m));
1128   }
1129
1130  out:
1131   conn->context_type = SILC_ID_NONE;
1132   conn->client_entry = NULL;
1133   silc_schedule_task_add_timeout(client->schedule,
1134                                  silc_client_autoneg_key_finish,
1135                                  client_entry, 0, 1);
1136 }
1137
1138 /* Auto-negotiate private message key with the remote client using the
1139    SKE protocol, which is tunneled through the SILC network inside private
1140    messages shared between the us and the remote client.
1141
1142    This operation is naturally asynchronous and will involve exchanging
1143    multiple messages back and forth.  Despite this, we don't run this
1144    operation in own FSM thread here, but instead will use the SKE library
1145    to do the asynchronous operation which we can abort at any time in
1146    case user disconnects.
1147
1148    Messages and packets we receive during this operation will be processed
1149    in the normal connection thread. */
1150
1151 SilcBool
1152 silc_client_autoneg_private_message_key(SilcClient client,
1153                                         SilcClientConnection conn,
1154                                         SilcClientEntry client_entry,
1155                                         SilcPacket initiator_packet,
1156                                         SilcMessageFlags flags,
1157                                         SilcHash hash,
1158                                         unsigned char *data,
1159                                         SilcUInt32 data_len)
1160 {
1161   SilcClientAutonegMessageKey ake;
1162   SilcBool initiator = initiator_packet == NULL;
1163   SilcBuffer m;
1164
1165   SILC_LOG_DEBUG(("Start private message AKE as %s with %s",
1166                   initiator ? "initiator" : "responder",
1167                   client_entry->nickname));
1168
1169   if (client_entry->internal.op) {
1170     ake = client_entry->internal.ake;
1171     if (ake && data) {
1172       /* If generation has changed, we must abort this exchange and
1173          start a new one. */
1174       if (ake->generation != conn->internal->ake_generation) {
1175         SILC_LOG_DEBUG(("Abort ongoing AKE and start new one"));
1176         silc_async_abort(client_entry->internal.op, NULL, NULL);
1177       } else {
1178         SILC_LOG_DEBUG(("AKE is ongoing, queue the message"));
1179
1180         m = silc_buffer_alloc_size(data_len + 2);
1181         if (!m)
1182           return FALSE;
1183         SILC_PUT16_MSB(flags, m->data);
1184         silc_buffer_pull(m, 2);
1185         silc_buffer_put(m, data, data_len);
1186         silc_dlist_add(ake->messages, m);
1187         return TRUE;
1188       }
1189     } else {
1190       SILC_LOG_DEBUG(("Cannot start AKE, operation %p is ongoing",
1191                       client_entry->internal.op));
1192       return FALSE;
1193     }
1194   }
1195
1196   ake = silc_calloc(1, sizeof(*ake));
1197   if (!ake)
1198     return FALSE;
1199   ake->conn = conn;
1200   ake->generation = conn->internal->ake_generation;
1201
1202   ake->messages = silc_dlist_init();
1203   if (!ake->messages)
1204     goto err;
1205
1206   /* Wrap our packet stream to a generic stream for the private messages
1207      we are going to exchange.  We send the packets with packet flag
1208      SILC_PACKET_FLAG_PRIVMSG_KEY which is a lie, but is a way to get
1209      clients which do not support this protocol to ignore these messages.
1210      This kludge should be removed once support is everywhere and
1211      responder should look only for the SILC_MESSAGE_FLAG_PACKET. */
1212   ake->stream = silc_packet_stream_wrap(conn->stream,
1213                                         SILC_PACKET_PRIVATE_MESSAGE,
1214                                         SILC_PACKET_FLAG_PRIVMSG_KEY, FALSE,
1215                                         SILC_ID_NONE, NULL,
1216                                         SILC_ID_CLIENT, &client_entry->id,
1217                                         silc_client_autoneg_key_coder,
1218                                         client_entry);
1219   if (!ake->stream)
1220     goto err;
1221
1222   /* Create a new packet stream for the SKE library using the wrapped
1223      stream as the underlaying stream, in effect creating a tunnel to
1224      send SKE packets inside private message packets. */
1225   ake->ske_stream = silc_packet_stream_create(client->internal->packet_engine,
1226                                               conn->internal->schedule,
1227                                               ake->stream);
1228   if (!ake->ske_stream)
1229     goto err;
1230
1231   silc_packet_set_context(ake->ske_stream, client_entry);
1232   silc_packet_set_ids(ake->ske_stream, SILC_ID_CLIENT, conn->local_id,
1233                       SILC_ID_CLIENT, &client_entry->id);
1234
1235   /* Link to the new packet stream to intercept the packets before they
1236      go to SKE library so that we can do additional checks and decide if
1237      we really want to process the packets. */
1238   if (!silc_packet_stream_link(ake->ske_stream, &autoneg_key_ske_cbs, NULL,
1239                                1000001, SILC_PACKET_ANY, -1))
1240     goto err;
1241
1242   /* Create SKE */
1243   ake->ske = silc_ske_alloc(client->rng, conn->internal->schedule,
1244                             conn->internal->params.repository,
1245                             conn->public_key, conn->private_key,
1246                             client_entry);
1247   if (!ake->ske)
1248     goto err;
1249
1250   silc_ske_set_callbacks(ake->ske, silc_client_autoneg_key_verify_pubkey,
1251                          silc_client_autoneg_key_done, client_entry);
1252   ake->params.version = client->internal->silc_client_version;
1253   ake->params.probe_timeout_secs = 5;
1254   ake->params.timeout_secs = 120;
1255   ake->params.flags = SILC_SKE_SP_FLAG_MUTUAL | SILC_SKE_SP_FLAG_PFS;
1256   ake->params.small_proposal = TRUE;
1257   ake->params.no_acks = TRUE;
1258
1259   if (client_entry->internal.send_key &&
1260       client_entry->internal.ake_generation == ake->generation) {
1261     /* Security properties for rekey */
1262     SilcSKESecurityProperties prop = silc_calloc(1, sizeof(*prop));
1263     if (!prop)
1264       goto err;
1265     silc_cipher_alloc(silc_cipher_get_name(client_entry->internal.send_key),
1266                       &prop->cipher);
1267     silc_hmac_alloc(silc_hmac_get_name(client_entry->internal.hmac_send),
1268                     NULL, &prop->hmac);
1269     silc_hash_alloc(silc_hash_get_name(silc_hmac_get_hash(
1270                         client_entry->internal.hmac_send)), &prop->hash);
1271     prop->public_key = silc_pkcs_public_key_copy(client_entry->public_key);
1272     silc_ske_group_get_by_number(2, &prop->group);
1273     prop->flags = ake->params.flags;
1274     ake->params.prop = prop;
1275   }
1276
1277   /* Start key exchange, responder is started in the packet callback  */
1278   if (initiator) {
1279     ake->ske_op = silc_ske_initiator(ake->ske, ake->ske_stream, &ake->params,
1280                                      NULL);
1281     if (!ake->ske_op)
1282       goto err;
1283   }
1284
1285   /* Finally, set up the client entry */
1286   client_entry->internal.op = silc_async_alloc(silc_client_autoneg_key_abort,
1287                                                NULL, client_entry);
1288   if (!client_entry->internal.op)
1289     goto err;
1290   client_entry->internal.ake = ake;
1291   client_entry->internal.no_ake = FALSE;
1292   client_entry->internal.prv_resp = !initiator;
1293   silc_client_ref_client(client, conn, client_entry);
1294
1295   /* As responder reinject the packet to the new stream so it gets decoded
1296      from the private message payload. */
1297   if (initiator_packet)
1298     silc_packet_stream_inject(conn->stream, initiator_packet);
1299
1300   /* Save the initial message, it will be sent after the key has been
1301      negotiated. */
1302   if (data && data_len) {
1303     m = silc_buffer_alloc_size(data_len + 2);
1304     if (m) {
1305       SILC_PUT16_MSB(flags, m->data);
1306       silc_buffer_pull(m, 2);
1307       silc_buffer_put(m, data, data_len);
1308       silc_dlist_add(ake->messages, m);
1309     }
1310     if (hash)
1311       silc_hash_alloc(silc_hash_get_name(hash), &ake->hash);
1312   }
1313
1314   return TRUE;
1315
1316  err:
1317   if (ake->ske)
1318     silc_ske_free(ake->ske);
1319   if (ake->ske_stream) {
1320     silc_packet_stream_unlink(ake->ske_stream, &autoneg_key_ske_cbs, NULL);
1321     silc_packet_stream_destroy(ake->ske_stream);
1322   } else if (ake->stream)
1323     silc_stream_destroy(ake->stream);
1324   silc_dlist_uninit(ake->messages);
1325   silc_free(ake);
1326   return FALSE;
1327 }
1328
1329 /* Sets away `message'.  The away message may be set when the client's
1330    mode is changed to SILC_UMODE_GONE and the client whishes to reply
1331    to anyone who sends private message.  The `message' will be sent
1332    automatically back to the the client who send private message.  If
1333    away message is already set this replaces the old message with the
1334    new one.  If `message' is NULL the old away message is removed.
1335    The sender may freely free the memory of the `message'. */
1336
1337 SilcBool silc_client_set_away_message(SilcClient client,
1338                                       SilcClientConnection conn,
1339                                       char *message)
1340 {
1341   if (!client || !conn)
1342     return FALSE;
1343
1344   if (!message) {
1345     silc_free(conn->internal->away_message);
1346     conn->internal->away_message = NULL;
1347     return TRUE;
1348   }
1349
1350   if (conn->internal->away_message)
1351     silc_free(conn->internal->away_message);
1352
1353   conn->internal->away_message = strdup(message);
1354   if (!conn->internal->away_message)
1355     return FALSE;
1356
1357   return TRUE;
1358 }