1 /*
2 
3   client_prvmsg.c
4 
5   Author: Pekka Riikonen <priikone@silcnet.org>
6 
7   Copyright (C) 1997 - 2014 Pekka Riikonen
8 
9   The contents of this file are subject to one of the Licenses specified
10   in the COPYING file;  You may not use this file except in compliance
11   with the License.
12 
13   The software distributed under the License is distributed on an "AS IS"
14   basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15   KIND, either expressed or implied.  See the COPYING file for more
16   information.
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 
silc_client_send_private_message(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry,SilcMessageFlags flags,SilcHash hash,unsigned char * data,SilcUInt32 data_len)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 
silc_client_private_message_resolved(SilcClient client,SilcClientConnection conn,SilcStatus status,SilcDList clients,void * context)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 
SILC_FSM_STATE(silc_client_private_message)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 
SILC_FSM_STATE(silc_client_private_message_error)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 
silc_client_private_message_wait_init(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry)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 
silc_client_private_message_wait_uninit(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry)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 
silc_client_private_message_wait(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry,SilcMessagePayload * payload)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
silc_client_send_private_message_key_request(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry)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 
silc_client_private_message_key_cb(SilcClient client,SilcClientConnection conn,SilcStatus status,SilcDList clients,void * context)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 
SILC_FSM_STATE(silc_client_private_message_key)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 
silc_client_add_private_message_key(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry,const char * cipher,const char * hmac,unsigned char * key,SilcUInt32 key_len)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 
silc_client_add_private_message_key_ske(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry,const char * cipher,const char * hmac,SilcSKEKeyMaterial keymat)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 
silc_client_del_private_message_key(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry)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
silc_client_list_private_message_keys(SilcClient client,SilcClientConnection conn,SilcUInt32 * key_count)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 
silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,SilcUInt32 key_count)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
silc_client_private_message_key_is_set(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry)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 
silc_client_autoneg_key_free(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry)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 
SILC_TASK_CALLBACK(silc_client_autoneg_key_finish)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
silc_client_autoneg_key_abort(SilcAsyncOperation op,void * context)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
silc_client_autoneg_key_recv_ske(SilcPacketEngine engine,SilcPacketStream stream,SilcPacket packet,void * callback_context,void * stream_context)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 
silc_client_autoneg_key_coder(SilcStream stream,SilcStreamStatus status,SilcBuffer buffer,void * context)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
silc_client_autoneg_key_verify_pubkey_cb(SilcBool success,void * context)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
silc_client_autoneg_key_verify_pubkey(SilcSKE ske,SilcPublicKey public_key,void * context,SilcSKEVerifyCbCompletion completion,void * completion_context)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 
silc_client_autoneg_key_done(SilcSKE ske,SilcSKEStatus status,SilcSKESecurityProperties prop,SilcSKEKeyMaterial keymat,SilcSKERekeyMaterial rekey,void * context)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
silc_client_autoneg_private_message_key(SilcClient client,SilcClientConnection conn,SilcClientEntry client_entry,SilcPacket initiator_packet,SilcMessageFlags flags,SilcHash hash,unsigned char * data,SilcUInt32 data_len)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 
silc_client_set_away_message(SilcClient client,SilcClientConnection conn,char * message)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 }
1359