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