-/* Timeout callback for unsuccessful rekey. The rekey did not go through
- for some reason. */
-
-SILC_TASK_CALLBACK(silc_server_rekey_timeout)
-{
- SilcServerRekeyInternalContext *ctx = context;
- SilcServer server = app_context;
- SilcSocketConnection sock = ctx->sock;
-
- SILC_LOG_DEBUG(("Timeout occurred in rekey protocol with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- SILC_LOG_WARNING(("Timeout occurred in rekey protocol with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- if (sock->protocol) {
- silc_protocol_cancel(sock->protocol, server->schedule);
- silc_protocol_free(sock->protocol);
- sock->protocol = NULL;
- }
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_socket_free(sock);
- silc_free(ctx);
-
- /* Disconnect since we failed to rekey, the keys are probably wrong. */
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-
- /* Reconnect */
- if (sock->type != SILC_SOCKET_TYPE_CLIENT)
- silc_server_create_connections(server);
-}
-
-/* A timeout callback for the re-key. We will be the initiator of the
- re-key protocol. */
-
-SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback)
-{
- SilcServer server = app_context;
- SilcSocketConnection sock = (SilcSocketConnection)context;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
- SilcProtocol protocol;
- SilcServerRekeyInternalContext *proto_ctx;
-
- if (!idata)
- return;
-
- /* Do not execute rekey with disabled connections, as it would not
- go through anyway. */
- if (idata->status & SILC_IDLIST_STATUS_DISABLED)
- return;
-
- /* If rekey protocol is active already wait for it to finish */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)
- return;
-
- /* If any other protocol is active do not start this protocol yet. */
- if (sock->protocol) {
- SILC_LOG_DEBUG(("Waiting for other protocol to finish before rekeying"));
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback,
- sock, 60, 0, SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_NORMAL);
- return;
- }
-
- SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- /* Allocate internal protocol context. This is sent as context
- to the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->server = (void *)server;
- proto_ctx->sock = silc_socket_dup(sock);
- proto_ctx->responder = FALSE;
- proto_ctx->pfs = idata->rekey->pfs;
-
- /* Perform rekey protocol. Will call the final callback after the
- protocol is over. */
- silc_protocol_alloc(SILC_PROTOCOL_SERVER_REKEY,
- &protocol, proto_ctx, silc_server_rekey_final);
- sock->protocol = protocol;
-
- /* Register timeout callback in case the rekey does not go through. */
- proto_ctx->timeout_task =
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_timeout,
- proto_ctx,
- (idata->rekey->timeout >
- server->config->key_exchange_timeout ?
- idata->rekey->timeout :
- server->config->key_exchange_timeout * 4), 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
-
- /* Run the protocol */
- silc_protocol_execute(protocol, server->schedule, 0, 0);
-}
-
-/* The final callback for the REKEY protocol. This will actually take the
- new key material into use. */
-
-SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcServerRekeyInternalContext *ctx =
- (SilcServerRekeyInternalContext *)protocol->context;
- SilcServer server = (SilcServer)ctx->server;
- SilcSocketConnection sock = ctx->sock;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
-
- if (ctx->timeout_task)
- silc_schedule_task_del(server->schedule, ctx->timeout_task);
-
- if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
- /* Error occured during protocol */
- SILC_LOG_ERROR(("Error occurred during rekey protocol with "
- "%s (%s)", sock->hostname, sock->ip));
- silc_protocol_cancel(protocol, server->schedule);
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_socket_free(sock);
- silc_free(ctx);
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-
- /* Reconnect */
- if (sock->type != SILC_SOCKET_TYPE_CLIENT)
- silc_server_create_connections(server);
- return;
- }
-
- SILC_LOG_DEBUG(("Rekey protocol completed with %s:%d [%s]",
- sock->hostname, sock->port,
- (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
- sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
- sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
- "Router")));
-
- /* Purge the outgoing data queue to assure that all rekey packets really
- go to the network before we quit the protocol. */
- silc_server_packet_queue_purge(server, sock);
-
- /* Re-register re-key timeout */
- if (ctx->responder == FALSE)
- silc_schedule_task_add(server->schedule, sock->sock,
- silc_server_rekey_callback,
- sock, idata->rekey->timeout, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-
- /* Cleanup */
- silc_protocol_free(protocol);
- sock->protocol = NULL;
- if (ctx->packet)
- silc_packet_context_free(ctx->packet);
- if (ctx->ske)
- silc_ske_free(ctx->ske);
- silc_socket_free(sock);
- silc_free(ctx);
-}
-