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 */
47 /* Packet sending function used by the SKE in the key agreement process. */
49 static void silc_client_key_agreement_send_packet(SilcSKE ske,
54 SilcProtocol protocol = (SilcProtocol)context;
55 SilcClientKEInternalContext *ctx =
56 (SilcClientKEInternalContext *)protocol->context;
59 /* Send the packet immediately. We will assure that the packet is not
60 encrypted by setting the socket's user_data pointer to NULL. The
61 silc_client_packet_send would take the keys (wrong keys that is,
62 because user_data is the current SilcClientConnection) from it and
63 we cannot allow that. The packets are never encrypted when doing SKE
64 with another client. */
65 tmp = ske->sock->user_data;
66 ske->sock->user_data = NULL;
67 silc_client_packet_send(ctx->client, ske->sock, type, NULL, 0, NULL, NULL,
68 packet->data, packet->len, TRUE);
69 ske->sock->user_data = tmp;
72 /* Timeout callback that is called to close the connection and free the
73 socket connection data. */
75 SILC_TASK_CALLBACK(silc_client_key_agreement_close)
77 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
79 silc_schedule_unset_listen_fd(ke->client->schedule, ke->sock->sock);
80 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
81 silc_net_close_connection(ke->sock->sock);
82 silc_net_close_connection(ke->fd);
83 silc_socket_free(ke->sock);
87 /* This callback is called after the key agreement protocol has been
88 performed. This calls the final completion callback for the application. */
90 SILC_TASK_CALLBACK(silc_client_key_agreement_final)
92 SilcProtocol protocol = (SilcProtocol)context;
93 SilcClientKEInternalContext *ctx =
94 (SilcClientKEInternalContext *)protocol->context;
95 SilcClient client = (SilcClient)ctx->client;
96 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)ctx->context;
98 SILC_LOG_DEBUG(("Start"));
100 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
101 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
102 /* Error occured during protocol */
103 ke->client_entry->ke = NULL;
104 ke->completion(ke->client, ke->conn, ke->client_entry,
105 SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
106 silc_ske_free_key_material(ctx->keymat);
110 /* Pass the negotiated key material to the application. The application
111 is responsible of freeing the key material. */
112 ke->client_entry->ke = NULL;
113 ke->completion(ke->client, ke->conn, ke->client_entry,
114 SILC_KEY_AGREEMENT_OK, ctx->keymat, ke->context);
117 silc_protocol_free(protocol);
119 silc_ske_free(ctx->ske);
121 silc_free(ctx->dest_id);
122 silc_task_unregister_by_fd(client->io_queue, ke->fd);
123 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
124 silc_net_close_connection(ke->fd);
126 silc_task_unregister(client->timeout_queue, ke->timeout);
127 silc_client_del_socket(ke->client, ke->sock);
129 silc_task_register(client->timeout_queue, 0,
130 silc_client_key_agreement_close,
132 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
137 /* Key agreement callback that is called when remote end has initiated
138 the key agreement protocol. This accepts the incoming TCP/IP connection
139 for the key agreement protocol. */
141 SILC_TASK_CALLBACK(silc_client_process_key_agreement)
143 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
144 SilcClient client = ke->client;
145 SilcClientConnection conn = ke->conn;
146 SilcSocketConnection newsocket;
147 SilcClientKEInternalContext *proto_ctx;
150 SILC_LOG_DEBUG(("Start"));
152 sock = silc_net_accept_connection(ke->fd);
154 client->ops->say(client, conn,
155 "Could not accept key agreement connection: ",
157 ke->client_entry->ke = NULL;
158 ke->completion(ke->client, ke->conn, ke->client_entry,
159 SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
160 silc_task_unregister_by_fd(client->io_queue, ke->fd);
161 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
162 silc_net_close_connection(ke->fd);
164 silc_task_unregister(client->timeout_queue, ke->timeout);
169 /* Set socket options */
170 silc_net_set_socket_nonblock(sock);
171 silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
173 /* Create socket for this connection (it is of type UNKNOWN since this
174 really is not a real SILC connection. It is only for the key
175 agreement protocol). */
176 silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, (void *)conn, &newsocket);
177 ke->sock = newsocket;
179 /* Perform name and address lookups for the remote host. */
180 silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
181 if (!newsocket->hostname && !newsocket->ip) {
182 client->ops->say(client, conn,
183 "Could not resolve the remote IP or hostname");
184 ke->client_entry->ke = NULL;
185 ke->completion(ke->client, ke->conn, ke->client_entry,
186 SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
187 silc_task_unregister_by_fd(client->io_queue, ke->fd);
188 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
189 silc_net_close_connection(ke->fd);
191 silc_task_unregister(client->timeout_queue, ke->timeout);
195 if (!newsocket->hostname)
196 newsocket->hostname = strdup(newsocket->ip);
197 newsocket->port = silc_net_get_remote_port(sock);
198 silc_client_add_socket(client, newsocket);
200 /* Allocate internal context for key exchange protocol. This is
201 sent as context for the protocol. */
202 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
203 proto_ctx->client = client;
204 proto_ctx->sock = newsocket;
205 proto_ctx->rng = client->rng;
206 proto_ctx->responder = TRUE;
207 proto_ctx->context = context;
208 proto_ctx->send_packet = silc_client_key_agreement_send_packet;
209 proto_ctx->verify = silc_client_protocol_ke_verify_key;
211 /* Prepare the connection for key exchange protocol. We allocate the
212 protocol but will not start it yet. The connector will be the
213 initiator of the protocol thus we will wait for initiation from
214 there before we start the protocol. */
215 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
216 &newsocket->protocol, proto_ctx,
217 silc_client_key_agreement_final);
219 /* Register the connection for network input and output. This sets
220 that scheduler will listen for incoming packets for this connection
221 and sets that outgoing packets may be sent to this connection as well.
222 However, this doesn't set the scheduler for outgoing traffic, it
223 will be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
224 later when outgoing data is available. */
225 context = (void *)client;
226 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(sock);
229 /* Timeout occured during key agreement. This means that the key agreement
230 protocol was not completed in the specified timeout. We will call the
231 completion callback. */
233 SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
235 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
237 ke->client_entry->ke = NULL;
238 ke->completion(ke->client, ke->conn, ke->client_entry,
239 SILC_KEY_AGREEMENT_TIMEOUT, NULL, ke->context);
242 silc_client_del_socket(ke->client, ke->sock);
243 silc_socket_free(ke->sock);
245 ke->client_entry->ke = NULL;
247 silc_task_unregister_by_fd(ke->client->io_queue, ke->fd);
248 silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
249 silc_net_close_connection(ke->fd);
253 /* Sends key agreement request to the remote client indicated by the
254 `client_entry'. If the caller provides the `hostname' and the `port'
255 arguments then the library will bind the client to that hostname and
256 that port for the key agreement protocol. It also sends the `hostname'
257 and the `port' in the key agreement packet to the remote client. This
258 would indicate that the remote client may initiate the key agreement
259 protocol to the `hostname' on the `port'. If port is zero then the
260 bound port is undefined (the operating system defines it).
262 If the `hostname' and `port' is not provided then empty key agreement
263 packet is sent to the remote client. The remote client may reply with
264 the same packet including its hostname and port. If the library receives
265 the reply from the remote client the `key_agreement' client operation
266 callback will be called to verify whether the user wants to perform the
267 key agreement or not.
269 NOTE: If the application provided the `hostname' and the `port' and the
270 remote side initiates the key agreement protocol it is not verified
271 from the user anymore whether the protocol should be executed or not.
272 By setting the `hostname' and `port' the user gives permission to
273 perform the protocol (we are responder in this case).
275 NOTE: If the remote side decides not to initiate the key agreement
276 or decides not to reply with the key agreement packet then we cannot
277 perform the key agreement at all. If the key agreement protocol is
278 performed the `completion' callback with the `context' will be called.
279 If remote side decides to ignore the request the `completion' will be
280 called after the specified timeout, `timeout_secs'.
282 NOTE: There can be only one active key agreement for one client entry.
283 Before setting new one, the old one must be finished (it is finished
284 after calling the completion callback) or the function
285 silc_client_abort_key_agreement must be called. */
287 void silc_client_send_key_agreement(SilcClient client,
288 SilcClientConnection conn,
289 SilcClientEntry client_entry,
293 SilcKeyAgreementCallback completion,
296 SilcSocketConnection sock = conn->sock;
297 SilcClientKeyAgreement ke = NULL;
300 assert(client_entry);
302 if (client_entry->ke)
305 /* Create the listener if hostname and port was provided */
307 ke = silc_calloc(1, sizeof(*ke));
308 ke->fd = silc_net_create_server(port, hostname);
311 client->ops->say(client, conn,
312 "Cannot create listener on %s on port %d: %s",
313 hostname, port, strerror(errno));
314 completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
322 ke->client_entry = client_entry;
323 ke->completion = completion;
324 ke->context = context;
326 /* Add listener task to the queue. This task receives the key
328 silc_task_register(client->io_queue, ke->fd,
329 silc_client_process_key_agreement,
332 SILC_TASK_PRI_NORMAL);
334 /* Register a timeout task that will be executed if the connector
335 will not start the key exchange protocol within the specified
337 ke->timeout = silc_task_register(client->timeout_queue, 0,
338 silc_client_key_agreement_timeout,
339 (void *)ke, timeout_secs, 0,
340 SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
343 /* Encode the key agreement payload */
344 buffer = silc_key_agreement_payload_encode(hostname,
346 silc_net_get_local_port(ke->fd));
348 /* Send the key agreement packet to the client */
349 silc_client_packet_send(client, sock, SILC_PACKET_KEY_AGREEMENT,
350 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
351 buffer->data, buffer->len, FALSE);
356 silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
360 /* Create connection to server asynchronously */
361 sock = silc_net_create_connection_async(ctx->port, ctx->host);
365 /* Register task that will receive the async connect and will
367 ctx->task = silc_task_register(ctx->client->io_queue, sock,
368 silc_client_perform_key_agreement_start,
371 SILC_TASK_PRI_NORMAL);
372 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
373 silc_schedule_set_listen_fd(ctx->client->schedule, sock, ctx->task->iomask);
380 /* Routine used by silc_client_perform_key_agreement to create connection
381 to the remote client on specified port. */
384 silc_client_connect_to_client(SilcClient client,
385 SilcClientConnection conn, int port,
386 char *host, void *context)
388 SilcClientInternalConnectContext *ctx;
390 /* Allocate internal context for connection process. This is
391 needed as we are doing async connecting. */
392 ctx = silc_calloc(1, sizeof(*ctx));
393 ctx->client = client;
395 ctx->host = strdup(host);
398 ctx->context = context;
400 /* Do the actual connecting process */
401 return silc_client_connect_to_client_internal(ctx);
404 /* Callback that is called after connection has been created. This actually
405 starts the key agreement protocol. This is initiator function. */
407 SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
409 SilcClientInternalConnectContext *ctx =
410 (SilcClientInternalConnectContext *)context;
411 SilcClient client = ctx->client;
412 SilcClientConnection conn = ctx->conn;
413 SilcClientKeyAgreement ke = (SilcClientKeyAgreement)ctx->context;
414 int opt, opt_len = sizeof(opt);
416 SILC_LOG_DEBUG(("Start"));
418 /* Check the socket status as it might be in error */
419 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
421 if (ctx->tries < 2) {
422 /* Connection failed but lets try again */
423 client->ops->say(client, conn, "Could not connect to client %s: %s",
424 ctx->host, strerror(opt));
425 client->ops->say(client, conn,
426 "Connecting to port %d of client %s resumed",
427 ctx->port, ctx->host);
429 /* Unregister old connection try */
430 silc_schedule_unset_listen_fd(client->schedule, fd);
431 silc_net_close_connection(fd);
432 silc_task_unregister(client->io_queue, ctx->task);
435 silc_client_connect_to_client_internal(ctx);
438 /* Connection failed and we won't try anymore */
439 client->ops->say(client, conn, "Could not connect to client %s: %s",
440 ctx->host, strerror(opt));
441 silc_schedule_unset_listen_fd(client->schedule, fd);
442 silc_net_close_connection(fd);
443 silc_task_unregister(client->io_queue, ctx->task);
444 silc_free(ctx->host);
447 /* Call the completion callback */
448 ke->completion(ke->client, ke->conn, ke->client_entry,
449 SILC_KEY_AGREEMENT_FAILURE, NULL, ke->context);
455 silc_schedule_unset_listen_fd(client->schedule, fd);
456 silc_task_unregister(client->io_queue, ctx->task);
460 /* Now actually perform the key agreement protocol */
461 silc_client_perform_key_agreement_fd(ke->client, ke->conn,
462 ke->client_entry, ke->fd, ctx->host,
463 ke->completion, ke->context);
465 silc_free(ctx->host);
469 /* Performs the actual key agreement protocol. Application may use this
470 to initiate the key agreement protocol. This can be called for example
471 after the application has received the `key_agreement' client operation,
472 and did not return TRUE from it.
474 The `hostname' is the remote hostname (or IP address) and the `port'
475 is the remote port. The `completion' callback with the `context' will
476 be called after the key agreement protocol.
478 NOTE: If the application returns TRUE in the `key_agreement' client
479 operation the library will automatically start the key agreement. In this
480 case the application must not call this function. However, application
481 may choose to just ignore the `key_agreement' client operation (and
482 merely just print information about it on the screen) and call this
483 function when the user whishes to do so (by, for example, giving some
484 specific command). Thus, the API provides both, automatic and manual
485 initiation of the key agreement. Calling this function is the manual
486 initiation and returning TRUE in the `key_agreement' client operation
487 is the automatic initiation. */
489 void silc_client_perform_key_agreement(SilcClient client,
490 SilcClientConnection conn,
491 SilcClientEntry client_entry,
494 SilcKeyAgreementCallback completion,
497 SilcClientKeyAgreement ke;
499 SILC_LOG_DEBUG(("Start"));
501 assert(client_entry && hostname && port);
503 ke = silc_calloc(1, sizeof(*ke));
506 ke->client_entry = client_entry;
507 ke->completion = completion;
508 ke->context = context;
510 /* Connect to the remote client */
511 ke->fd = silc_client_connect_to_client(client, conn, port, hostname, ke);
513 completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
520 /* Same as above but application has created already the connection to
521 the remote host. The `sock' is the socket to the remote connection.
522 Application can use this function if it does not want the client library
523 to create the connection. */
525 void silc_client_perform_key_agreement_fd(SilcClient client,
526 SilcClientConnection conn,
527 SilcClientEntry client_entry,
530 SilcKeyAgreementCallback completion,
533 SilcClientKeyAgreement ke;
534 SilcClientKEInternalContext *proto_ctx;
535 SilcProtocol protocol;
537 SILC_LOG_DEBUG(("Start"));
539 assert(client_entry);
541 ke = silc_calloc(1, sizeof(*ke));
544 ke->client_entry = client_entry;
546 ke->completion = completion;
547 ke->context = context;
549 /* Allocate new socket connection object */
550 silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, (void *)conn, &ke->sock);
551 silc_client_add_socket(client, ke->sock);
552 ke->sock->hostname = strdup(hostname);
553 ke->sock->port = silc_net_get_remote_port(sock);
555 /* Allocate internal context for key exchange protocol. This is
556 sent as context for the protocol. */
557 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
558 proto_ctx->client = client;
559 proto_ctx->sock = ke->sock;
560 proto_ctx->rng = client->rng;
561 proto_ctx->responder = FALSE;
562 proto_ctx->context = ke;
563 proto_ctx->send_packet = silc_client_key_agreement_send_packet;
564 proto_ctx->verify = silc_client_protocol_ke_verify_key;
566 /* Perform key exchange protocol. */
567 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
568 &protocol, (void *)proto_ctx,
569 silc_client_key_agreement_final);
570 ke->sock->protocol = protocol;
572 /* Register the connection for network input and output. This sets
573 that scheduler will listen for incoming packets for this connection
574 and sets that outgoing packets may be sent to this connection as well.
575 However, this doesn't set the scheduler for outgoing traffic, it will
576 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
577 later when outgoing data is available. */
578 context = (void *)client;
579 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(sock);
581 /* Execute the protocol */
582 silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
585 /* This function can be called to unbind the hostname and the port for
586 the key agreement protocol. However, this function has effect only
587 before the key agreement protocol has been performed. After it has
588 been performed the library will automatically unbind the port. The
589 `client_entry' is the client to which we sent the key agreement
592 void silc_client_abort_key_agreement(SilcClient client,
593 SilcClientConnection conn,
594 SilcClientEntry client_entry)
596 assert(client_entry);
598 if (client_entry->ke) {
599 if (client_entry->ke->sock) {
600 silc_client_del_socket(client_entry->ke->client, client_entry->ke->sock);
601 silc_socket_free(client_entry->ke->sock);
603 client_entry->ke = NULL;
604 silc_task_unregister_by_fd(client->io_queue, client_entry->ke->fd);
605 if (client_entry->ke->timeout)
606 silc_task_unregister(client->timeout_queue,
607 client_entry->ke->timeout);
608 silc_free(client_entry->ke);
612 /* Callback function that is called after we've resolved the client
613 information who sent us the key agreement packet from the server.
614 We actually call the key_agreement client operation now. */
617 silc_client_key_agreement_resolve_cb(SilcClient client,
618 SilcClientConnection conn,
619 SilcClientEntry *clients,
620 uint32 clients_count,
623 SilcPacketContext *packet = (SilcPacketContext *)context;
624 SilcKeyAgreementPayload payload;
626 SilcKeyAgreementCallback completion;
627 void *completion_context;
632 /* Parse the key agreement payload */
633 payload = silc_key_agreement_payload_parse(packet->buffer);
637 /* Call the key_agreement client operation */
638 ret = client->ops->key_agreement(client, conn, clients[0],
639 silc_key_agreement_get_hostname(payload),
640 silc_key_agreement_get_port(payload),
641 &completion, &completion_context);
643 /* If the user returned TRUE then we'll start the key agreement right
644 here and right now. */
646 silc_client_perform_key_agreement(client, conn, clients[0],
647 silc_key_agreement_get_hostname(payload),
648 silc_key_agreement_get_port(payload),
649 completion, completion_context);
651 silc_key_agreement_payload_free(payload);
654 silc_packet_context_free(packet);
657 /* Received Key Agreement packet from remote client. Process the packet
658 and resolve the client information from the server before actually
659 letting the application know that we've received this packet. Then
660 call the key_agreement client operation and let the user decide
661 whether we perform the key agreement protocol now or not. */
663 void silc_client_key_agreement(SilcClient client,
664 SilcSocketConnection sock,
665 SilcPacketContext *packet)
667 SilcClientID *remote_id;
669 if (packet->src_id_type != SILC_ID_CLIENT)
672 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
677 silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
678 silc_client_key_agreement_resolve_cb,
679 silc_packet_context_dup(packet));
680 silc_free(remote_id);