5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 /* This file includes the Key Agreement packet processing and actual
22 key agreement routines. This file has nothing to do with the actual
23 connection key exchange protocol, it is implemented in the client.c
24 and in protocol.c. This file implements the client-to-client key
25 agreement as defined by the SILC protocol. */
27 #include "clientlibincludes.h"
28 #include "client_internal.h"
30 SILC_TASK_CALLBACK(silc_client_key_agreement_final);
31 SILC_TASK_CALLBACK(silc_client_process_key_agreement);
32 SILC_TASK_CALLBACK(silc_client_key_agreement_timeout);
33 SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start);
35 /* Key agreement context */
36 struct SilcClientKeyAgreementStruct {
38 SilcClientConnection conn;
39 int fd; /* Listening/connection socket */
40 SilcSocketConnection sock; /* Remote socket connection */
41 SilcClientEntry client_entry; /* Destination client */
42 SilcKeyAgreementCallback completion; /* Key agreement completion */
43 void *context; /* User context */
44 SilcTask timeout; /* Timeout task */
45 SilcClientKEInternalContext *proto_ctx; /* Key Exchange protocol context */
48 /* Packet sending function used by the SKE in the key agreement process. */
50 static void silc_client_key_agreement_send_packet(SilcSKE ske,
55 SilcProtocol protocol = (SilcProtocol)context;
56 SilcClientKEInternalContext *ctx =
57 (SilcClientKEInternalContext *)protocol->context;
60 /* Send the packet immediately. We will assure that the packet is not
61 encrypted by setting the socket's user_data pointer to NULL. The
62 silc_client_packet_send would take the keys (wrong keys that is,
63 because user_data is the current SilcClientConnection) from it and
64 we cannot allow that. The packets are never encrypted when doing SKE
65 with another client. */
66 tmp = ske->sock->user_data;
67 ske->sock->user_data = NULL;
68 silc_client_packet_send(ctx->client, ske->sock, type, NULL, 0, NULL, NULL,
69 packet->data, packet->len, TRUE);
70 ske->sock->user_data = tmp;
73 /* Timeout callback that is called to close the connection and free the
74 socket connection data. */
76 SILC_TASK_CALLBACK(silc_client_key_agreement_close)
78 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
80 silc_schedule_unset_listen_fd(ke->client->schedule, ke->sock->sock);
81 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
82 silc_net_close_connection(ke->sock->sock);
83 silc_net_close_connection(ke->fd);
84 silc_socket_free(ke->sock);
88 /* This callback is called after the key agreement protocol has been
89 performed. This calls the final completion callback for the application. */
91 SILC_TASK_CALLBACK(silc_client_key_agreement_final)
93 SilcProtocol protocol = (SilcProtocol)context;
94 SilcClientKEInternalContext *ctx =
95 (SilcClientKEInternalContext *)protocol->context;
96 SilcClient client = (SilcClient)ctx->client;
97 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)ctx->context;
99 SILC_LOG_DEBUG(("Start"));
101 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
102 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
103 /* Error occured during protocol */
104 ke->client_entry->ke = NULL;
105 ke->completion(ke->client, ke->conn, ke->client_entry,
106 SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
107 silc_ske_free_key_material(ctx->keymat);
111 /* Pass the negotiated key material to the application. The application
112 is responsible of freeing the key material. */
113 ke->client_entry->ke = NULL;
114 ke->completion(ke->client, ke->conn, ke->client_entry,
115 SILC_KEY_AGREEMENT_OK, ctx->keymat, ke->context);
118 silc_protocol_free(protocol);
120 silc_ske_free(ctx->ske);
122 silc_free(ctx->dest_id);
123 silc_schedule_task_del_by_fd(client->schedule, ke->fd);
124 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
125 silc_net_close_connection(ke->fd);
127 silc_schedule_task_del(client->schedule, ke->timeout);
128 silc_client_del_socket(ke->client, ke->sock);
130 silc_schedule_task_add(client->schedule, 0,
131 silc_client_key_agreement_close,
133 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
138 /* Key agreement callback that is called when remote end has initiated
139 the key agreement protocol. This accepts the incoming TCP/IP connection
140 for the key agreement protocol. */
142 SILC_TASK_CALLBACK(silc_client_process_key_agreement)
144 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
145 SilcClient client = ke->client;
146 SilcClientConnection conn = ke->conn;
147 SilcSocketConnection newsocket;
148 SilcClientKEInternalContext *proto_ctx;
151 SILC_LOG_DEBUG(("Start"));
153 sock = silc_net_accept_connection(ke->fd);
155 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
156 "Could not accept key agreement connection: ",
158 ke->client_entry->ke = NULL;
159 ke->completion(ke->client, ke->conn, ke->client_entry,
160 SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
161 silc_schedule_task_del_by_fd(client->schedule, ke->fd);
162 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
163 silc_net_close_connection(ke->fd);
165 silc_schedule_task_del(client->schedule, ke->timeout);
170 /* Set socket options */
171 silc_net_set_socket_nonblock(sock);
172 silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
174 /* Create socket for this connection (it is of type UNKNOWN since this
175 really is not a real SILC connection. It is only for the key
176 agreement protocol). */
177 silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, (void *)conn, &newsocket);
178 ke->sock = newsocket;
180 /* Perform name and address lookups for the remote host. */
181 silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
182 if (!newsocket->hostname && !newsocket->ip) {
183 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
184 "Could not resolve the remote IP or hostname");
185 ke->client_entry->ke = NULL;
186 ke->completion(ke->client, ke->conn, ke->client_entry,
187 SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
188 silc_schedule_task_del_by_fd(client->schedule, ke->fd);
189 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
190 silc_net_close_connection(ke->fd);
192 silc_schedule_task_del(client->schedule, ke->timeout);
196 if (!newsocket->hostname)
197 newsocket->hostname = strdup(newsocket->ip);
198 newsocket->port = silc_net_get_remote_port(sock);
199 silc_client_add_socket(client, newsocket);
201 /* Allocate internal context for key exchange protocol. This is
202 sent as context for the protocol. */
203 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
204 proto_ctx->client = client;
205 proto_ctx->sock = silc_socket_dup(newsocket);
206 proto_ctx->rng = client->rng;
207 proto_ctx->responder = TRUE;
208 proto_ctx->context = context;
209 proto_ctx->send_packet = silc_client_key_agreement_send_packet;
210 proto_ctx->verify = silc_client_protocol_ke_verify_key;
211 ke->proto_ctx = proto_ctx;
213 /* Prepare the connection for key exchange protocol. We allocate the
214 protocol but will not start it yet. The connector will be the
215 initiator of the protocol thus we will wait for initiation from
216 there before we start the protocol. */
217 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
218 &newsocket->protocol, proto_ctx,
219 silc_client_key_agreement_final);
221 /* Register the connection for network input and output. This sets
222 that scheduler will listen for incoming packets for this connection
223 and sets that outgoing packets may be sent to this connection as well.
224 However, this doesn't set the scheduler for outgoing traffic, it
225 will be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
226 later when outgoing data is available. */
227 context = (void *)client;
228 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(sock);
231 /* Timeout occured during key agreement. This means that the key agreement
232 protocol was not completed in the specified timeout. We will call the
233 completion callback. */
235 SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
237 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
239 ke->client_entry->ke = NULL;
240 ke->completion(ke->client, ke->conn, ke->client_entry,
241 SILC_KEY_AGREEMENT_TIMEOUT, NULL, ke->context);
244 silc_client_del_socket(ke->client, ke->sock);
245 silc_socket_free(ke->sock);
247 if (ke->proto_ctx && ke->proto_ctx->ske)
248 silc_ske_free(ke->proto_ctx->ske);
249 ke->client_entry->ke = NULL;
251 silc_schedule_task_del_by_fd(ke->client->schedule, ke->fd);
252 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
253 silc_net_close_connection(ke->fd);
257 /* Sends key agreement request to the remote client indicated by the
258 `client_entry'. If the caller provides the `hostname' and the `port'
259 arguments then the library will bind the client to that hostname and
260 that port for the key agreement protocol. It also sends the `hostname'
261 and the `port' in the key agreement packet to the remote client. This
262 would indicate that the remote client may initiate the key agreement
263 protocol to the `hostname' on the `port'. If port is zero then the
264 bound port is undefined (the operating system defines it).
266 If the `hostname' and `port' is not provided then empty key agreement
267 packet is sent to the remote client. The remote client may reply with
268 the same packet including its hostname and port. If the library receives
269 the reply from the remote client the `key_agreement' client operation
270 callback will be called to verify whether the user wants to perform the
271 key agreement or not.
273 NOTE: If the application provided the `hostname' and the `port' and the
274 remote side initiates the key agreement protocol it is not verified
275 from the user anymore whether the protocol should be executed or not.
276 By setting the `hostname' and `port' the user gives permission to
277 perform the protocol (we are responder in this case).
279 NOTE: If the remote side decides not to initiate the key agreement
280 or decides not to reply with the key agreement packet then we cannot
281 perform the key agreement at all. If the key agreement protocol is
282 performed the `completion' callback with the `context' will be called.
283 If remote side decides to ignore the request the `completion' will be
284 called after the specified timeout, `timeout_secs'.
286 NOTE: If the `hostname' and the `port' was not provided the `completion'
287 will not be called at all since this does nothing more than sending
288 a packet to the remote host.
290 NOTE: There can be only one active key agreement for one client entry.
291 Before setting new one, the old one must be finished (it is finished
292 after calling the completion callback) or the function
293 silc_client_abort_key_agreement must be called. */
295 void silc_client_send_key_agreement(SilcClient client,
296 SilcClientConnection conn,
297 SilcClientEntry client_entry,
298 const char *hostname,
299 const char *bindhost,
302 SilcKeyAgreementCallback completion,
305 SilcSocketConnection sock = conn->sock;
306 SilcClientKeyAgreement ke = NULL;
309 assert(client_entry);
311 if (client_entry->ke)
314 /* Create the listener if hostname and port was provided.
315 * also, use bindhost if it was specified.
319 ke = silc_calloc(1, sizeof(*ke));
322 ke->fd = silc_net_create_server(port, bindhost);
324 ke->fd = silc_net_create_server(port, hostname);
327 client->internal->ops->say(
328 client, conn, SILC_CLIENT_MESSAGE_ERROR,
329 "Cannot create listener on %s on port %d: %s",
330 (bindhost) ? bindhost:hostname, port, strerror(errno));
331 completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
340 ke->client_entry = client_entry;
341 ke->completion = completion;
342 ke->context = context;
344 /* Add listener task to the scheduler. This task receives the key
346 silc_schedule_task_add(client->schedule, ke->fd,
347 silc_client_process_key_agreement,
350 SILC_TASK_PRI_NORMAL);
352 /* Register a timeout task that will be executed if the connector
353 will not start the key exchange protocol within the specified
355 ke->timeout = silc_schedule_task_add(client->schedule, 0,
356 silc_client_key_agreement_timeout,
357 (void *)ke, timeout_secs, 0,
358 SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
361 /* Encode the key agreement payload */
362 buffer = silc_key_agreement_payload_encode(hostname,
364 silc_net_get_local_port(ke->fd));
366 /* Send the key agreement packet to the client */
367 silc_client_packet_send(client, sock, SILC_PACKET_KEY_AGREEMENT,
368 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
369 buffer->data, buffer->len, FALSE);
370 silc_buffer_free(buffer);
375 silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
379 /* Create connection to server asynchronously */
380 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
384 /* Register task that will receive the async connect and will
386 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
387 silc_client_perform_key_agreement_start,
390 SILC_TASK_PRI_NORMAL);
391 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
398 /* Routine used by silc_client_perform_key_agreement to create connection
399 to the remote client on specified port. */
402 silc_client_connect_to_client(SilcClient client,
403 SilcClientConnection conn, int port,
404 char *host, void *context)
406 SilcClientInternalConnectContext *ctx;
408 /* Allocate internal context for connection process. This is
409 needed as we are doing async connecting. */
410 ctx = silc_calloc(1, sizeof(*ctx));
411 ctx->client = client;
413 ctx->host = strdup(host);
416 ctx->context = context;
418 /* Do the actual connecting process */
419 return silc_client_connect_to_client_internal(ctx);
422 /* Callback that is called after connection has been created. This actually
423 starts the key agreement protocol. This is initiator function. */
425 SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
427 SilcClientInternalConnectContext *ctx =
428 (SilcClientInternalConnectContext *)context;
429 SilcClient client = ctx->client;
430 SilcClientConnection conn = ctx->conn;
431 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)ctx->context;
432 int opt, opt_len = sizeof(opt);
434 SILC_LOG_DEBUG(("Start"));
436 /* Check the socket status as it might be in error */
437 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
439 if (ctx->tries < 2) {
440 /* Connection failed but lets try again */
441 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
442 "Could not connect to client %s: %s",
443 ctx->host, strerror(opt));
444 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
445 "Connecting to port %d of client %s resumed",
446 ctx->port, ctx->host);
448 /* Unregister old connection try */
449 silc_schedule_unset_listen_fd(client->schedule, fd);
450 silc_net_close_connection(fd);
451 silc_schedule_task_del(client->schedule, ctx->task);
454 silc_client_connect_to_client_internal(ctx);
457 /* Connection failed and we won't try anymore */
458 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
459 "Could not connect to client %s: %s",
460 ctx->host, strerror(opt));
461 silc_schedule_unset_listen_fd(client->schedule, fd);
462 silc_net_close_connection(fd);
463 silc_schedule_task_del(client->schedule, ctx->task);
464 silc_free(ctx->host);
467 /* Call the completion callback */
468 ke->completion(ke->client, ke->conn, ke->client_entry,
469 SILC_KEY_AGREEMENT_FAILURE, NULL, ke->context);
475 silc_schedule_unset_listen_fd(client->schedule, fd);
476 silc_schedule_task_del(client->schedule, ctx->task);
480 /* Now actually perform the key agreement protocol */
481 silc_client_perform_key_agreement_fd(ke->client, ke->conn,
482 ke->client_entry, ke->fd, ctx->host,
483 ke->completion, ke->context);
485 silc_free(ctx->host);
489 /* Performs the actual key agreement protocol. Application may use this
490 to initiate the key agreement protocol. This can be called for example
491 after the application has received the `key_agreement' client operation,
492 and did not return TRUE from it.
494 The `hostname' is the remote hostname (or IP address) and the `port'
495 is the remote port. The `completion' callback with the `context' will
496 be called after the key agreement protocol.
498 NOTE: If the application returns TRUE in the `key_agreement' client
499 operation the library will automatically start the key agreement. In this
500 case the application must not call this function. However, application
501 may choose to just ignore the `key_agreement' client operation (and
502 merely just print information about it on the screen) and call this
503 function when the user whishes to do so (by, for example, giving some
504 specific command). Thus, the API provides both, automatic and manual
505 initiation of the key agreement. Calling this function is the manual
506 initiation and returning TRUE in the `key_agreement' client operation
507 is the automatic initiation. */
509 void silc_client_perform_key_agreement(SilcClient client,
510 SilcClientConnection conn,
511 SilcClientEntry client_entry,
514 SilcKeyAgreementCallback completion,
517 SilcClientKeyAgreement ke;
519 SILC_LOG_DEBUG(("Start"));
521 assert(client_entry && hostname && port);
523 ke = silc_calloc(1, sizeof(*ke));
526 ke->client_entry = client_entry;
527 ke->completion = completion;
528 ke->context = context;
530 /* Connect to the remote client */
531 ke->fd = silc_client_connect_to_client(client, conn, port, hostname, ke);
533 completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
540 /* Same as above but application has created already the connection to
541 the remote host. The `sock' is the socket to the remote connection.
542 Application can use this function if it does not want the client library
543 to create the connection. */
545 void silc_client_perform_key_agreement_fd(SilcClient client,
546 SilcClientConnection conn,
547 SilcClientEntry client_entry,
550 SilcKeyAgreementCallback completion,
553 SilcClientKeyAgreement ke;
554 SilcClientKEInternalContext *proto_ctx;
555 SilcProtocol protocol;
557 SILC_LOG_DEBUG(("Start"));
559 assert(client_entry);
561 ke = silc_calloc(1, sizeof(*ke));
564 ke->client_entry = client_entry;
566 ke->completion = completion;
567 ke->context = context;
569 /* Allocate new socket connection object */
570 silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, (void *)conn, &ke->sock);
571 silc_client_add_socket(client, ke->sock);
572 ke->sock->hostname = strdup(hostname);
573 ke->sock->port = silc_net_get_remote_port(sock);
575 /* Allocate internal context for key exchange protocol. This is
576 sent as context for the protocol. */
577 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
578 proto_ctx->client = client;
579 proto_ctx->sock = silc_socket_dup(ke->sock);
580 proto_ctx->rng = client->rng;
581 proto_ctx->responder = FALSE;
582 proto_ctx->context = ke;
583 proto_ctx->send_packet = silc_client_key_agreement_send_packet;
584 proto_ctx->verify = silc_client_protocol_ke_verify_key;
585 ke->proto_ctx = proto_ctx;
587 /* Perform key exchange protocol. */
588 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
589 &protocol, (void *)proto_ctx,
590 silc_client_key_agreement_final);
591 ke->sock->protocol = protocol;
593 /* Register the connection for network input and output. This sets
594 that scheduler will listen for incoming packets for this connection
595 and sets that outgoing packets may be sent to this connection as well.
596 However, this doesn't set the scheduler for outgoing traffic, it will
597 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
598 later when outgoing data is available. */
599 context = (void *)client;
600 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(sock);
602 /* Execute the protocol */
603 silc_protocol_execute(protocol, client->schedule, 0, 0);
606 /* This function can be called to unbind the hostname and the port for
607 the key agreement protocol. However, this function has effect only
608 before the key agreement protocol has been performed. After it has
609 been performed the library will automatically unbind the port. The
610 `client_entry' is the client to which we sent the key agreement
613 void silc_client_abort_key_agreement(SilcClient client,
614 SilcClientConnection conn,
615 SilcClientEntry client_entry)
617 assert(client_entry);
619 if (client_entry->ke) {
620 SilcClientKeyAgreement ke;
622 if (client_entry->ke->sock) {
623 silc_client_del_socket(client_entry->ke->client, client_entry->ke->sock);
624 silc_socket_free(client_entry->ke->sock);
626 silc_schedule_task_del_by_fd(client->schedule, client_entry->ke->fd);
627 if (client_entry->ke->timeout)
628 silc_schedule_task_del(client->schedule,
629 client_entry->ke->timeout);
630 ke = client_entry->ke;
631 client_entry->ke = NULL;
632 ke->completion(client, conn, client_entry,
633 SILC_KEY_AGREEMENT_ABORTED, NULL, ke->context);
638 /* Callback function that is called after we've resolved the client
639 information who sent us the key agreement packet from the server.
640 We actually call the key_agreement client operation now. */
643 silc_client_key_agreement_resolve_cb(SilcClient client,
644 SilcClientConnection conn,
645 SilcClientEntry *clients,
646 uint32 clients_count,
649 SilcPacketContext *packet = (SilcPacketContext *)context;
650 SilcKeyAgreementPayload payload;
652 SilcKeyAgreementCallback completion;
653 void *completion_context;
658 /* Parse the key agreement payload */
659 payload = silc_key_agreement_payload_parse(packet->buffer->data,
660 packet->buffer->len);
664 /* Call the key_agreement client operation */
665 ret = client->internal->ops->key_agreement(
666 client, conn, clients[0],
667 silc_key_agreement_get_hostname(payload),
668 silc_key_agreement_get_port(payload),
669 &completion, &completion_context);
671 /* If the user returned TRUE then we'll start the key agreement right
672 here and right now. */
674 silc_client_perform_key_agreement(client, conn, clients[0],
675 silc_key_agreement_get_hostname(payload),
676 silc_key_agreement_get_port(payload),
677 completion, completion_context);
679 silc_key_agreement_payload_free(payload);
682 silc_packet_context_free(packet);
685 /* Received Key Agreement packet from remote client. Process the packet
686 and resolve the client information from the server before actually
687 letting the application know that we've received this packet. Then
688 call the key_agreement client operation and let the user decide
689 whether we perform the key agreement protocol now or not. */
691 void silc_client_key_agreement(SilcClient client,
692 SilcSocketConnection sock,
693 SilcPacketContext *packet)
695 SilcClientID *remote_id;
697 if (packet->src_id_type != SILC_ID_CLIENT)
700 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
705 silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
706 silc_client_key_agreement_resolve_cb,
707 silc_packet_context_dup(packet));
708 silc_free(remote_id);