-/* Processes the received new Client ID from server. Old Client ID is
- deleted from cache and new one is added. */
-
-void silc_client_receive_new_id(SilcClient client,
- SilcClientConnection conn,
- SilcIDPayload idp)
-{
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- int connecting = FALSE;
- SilcClientID *client_id = silc_id_payload_get_id(idp);
- char *nickname;
-
- if (!conn->local_entry)
- connecting = TRUE;
-
- /* Delete old ID from ID cache */
- if (conn->local_id) {
- /* Check whether they are different */
- if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
- silc_free(client_id);
- return;
- }
-
- silc_idcache_del_by_context(conn->internal->client_cache,
- conn->local_entry);
- silc_free(conn->local_id);
- }
-
- /* Save the new ID */
-
- if (conn->local_id_data)
- silc_free(conn->local_id_data);
-
- conn->local_id = client_id;
- conn->local_id_data = silc_id_payload_get_data(idp);
- conn->local_id_data_len = silc_id_payload_get_len(idp);;
-
- if (!conn->local_entry)
- conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
-
- conn->local_entry->nickname = conn->nickname;
- if (!conn->local_entry->username)
- conn->local_entry->username = strdup(client->username);
- if (!conn->local_entry->server)
- conn->local_entry->server = strdup(conn->remote_host);
- conn->local_entry->id = conn->local_id;
- conn->local_entry->valid = TRUE;
- if (!conn->local_entry->channels)
- conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr,
- NULL, NULL,
- NULL, NULL, NULL,
- TRUE);
-
- /* Normalize nickname */
- nickname = silc_identifier_check(conn->nickname, strlen(conn->nickname),
- SILC_STRING_UTF8, 128, NULL);
- if (!nickname)
- return;
-
- /* Put it to the ID cache */
- silc_idcache_add(conn->internal->client_cache, nickname, conn->local_id,
- (void *)conn->local_entry, 0, NULL);
-
-#if 0
- if (connecting) {
- SilcBuffer sidp;
-
- /* Issue IDENTIFY command for itself to get resolved hostname
- correctly from server. */
- silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
- silc_client_command_reply_identify_i, 0,
- ++conn->cmd_ident);
- sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
- silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident, 1, 5, sidp->data, sidp->len);
- silc_buffer_free(sidp);
-
- if (!conn->internal->params.detach_data) {
- /* Send NICK command if the nickname was set by the application (and is
- not same as the username). Send this with little timeout. */
- if (client->nickname &&
- !silc_utf8_strcasecmp(client->nickname, client->username))
- silc_schedule_task_add(client->schedule, 0,
- silc_client_send_auto_nick, conn,
- 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-
- /* Notify application of successful connection. We do it here now that
- we've received the Client ID and are allowed to send traffic. */
- client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS);
-
- /* Issue INFO command to fetch the real server name and server
- information and other stuff. */
- silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
- silc_client_command_reply_info_i, 0,
- ++conn->cmd_ident);
- sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
- silc_client_command_send(client, conn, SILC_COMMAND_INFO,
- conn->cmd_ident, 1, 2, sidp->data, sidp->len);
- silc_buffer_free(sidp);
- } else {
- /* We are resuming session. Start resolving informations from the
- server we need to set the client libary in the state before
- detaching the session. The connect client operation is called
- after this is successfully completed */
- silc_client_resume_session(client, conn, silc_client_resume_session_cb,
- NULL);
- }
- }
-#endif /* 0 */
-}
-
-/* Removes a client entry from all channels it has joined. */
-
-void silc_client_remove_from_channels(SilcClient client,
- SilcClientConnection conn,
- SilcClientEntry client_entry)
-{
- SilcHashTableList htl;
- SilcChannelUser chu;
-
- silc_hash_table_list(client_entry->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
- silc_hash_table_del(chu->client->channels, chu->channel);
- silc_hash_table_del(chu->channel->user_list, chu->client);
- silc_free(chu);
- }
-
- silc_hash_table_list_reset(&htl);
-}
-
-/* Replaces `old' client entries from all channels to `new' client entry.
- This can be called for example when nickname changes and old ID entry
- is replaced from ID cache with the new one. If the old ID entry is only
- updated, then this fucntion needs not to be called. */
-
-void silc_client_replace_from_channels(SilcClient client,
- SilcClientConnection conn,
- SilcClientEntry old,
- SilcClientEntry new)
-{
- SilcHashTableList htl;
- SilcChannelUser chu;
-
- silc_hash_table_list(old->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
- /* Replace client entry */
- silc_hash_table_del(chu->client->channels, chu->channel);
- silc_hash_table_del(chu->channel->user_list, chu->client);
-
- chu->client = new;
- silc_hash_table_add(chu->channel->user_list, chu->client, chu);
- silc_hash_table_add(chu->client->channels, chu->channel, chu);
- }
- silc_hash_table_list_reset(&htl);
-}
-
-/* Registers failure timeout to process the received failure packet
- with timeout. */
-
-void silc_client_process_failure(SilcClient client,
- SilcClientConnection conn,
- SilcPacketContext *packet)
-{
- SilcUInt32 failure = 0;
-
- if (sock->protocol) {
- if (packet->buffer->len >= 4)
- SILC_GET32_MSB(failure, packet->buffer->data);
-
- /* Notify application */
- client->internal->ops->failure(client, sock->user_data, sock->protocol,
- SILC_32_TO_PTR(failure));
- }
-}
-
-/* A timeout callback for the re-key. We will be the initiator of the
- re-key protocol. */
-
-SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback)
-{
- SilcClientConnection conn = (SilcSocketConnection)context;
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcClient client = (SilcClient)conn->internal->rekey->context;
- SilcProtocol protocol;
- SilcClientRekeyInternalContext *proto_ctx;
-
- SILC_LOG_DEBUG(("Start"));
-
- /* If rekey protocol is active already wait for it to finish */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)
- return;
-
- /* Allocate internal protocol context. This is sent as context
- to the protocol. */
- proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
- proto_ctx->client = (void *)client;
- proto_ctx->sock = silc_socket_dup(sock);
- proto_ctx->responder = FALSE;
- proto_ctx->pfs = conn->internal->rekey->pfs;
-
- /* Perform rekey protocol. Will call the final callback after the
- protocol is over. */
- silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
- &protocol, proto_ctx, silc_client_rekey_final);
- sock->protocol = protocol;
-
- /* Run the protocol */
- silc_protocol_execute(protocol, client->schedule, 0, 0);
-}
-
-/* The final callback for the REKEY protocol. This will actually take the
- new key material into use. */
-
-SILC_TASK_CALLBACK(silc_client_rekey_final)
-{
- SilcProtocol protocol = (SilcProtocol)context;
- SilcClientRekeyInternalContext *ctx =
- (SilcClientRekeyInternalContext *)protocol->context;
- SilcClient client = (SilcClient)ctx->client;
- SilcClientConnection conn = ctx->sock;
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
-
- SILC_LOG_DEBUG(("Start"));
-
- if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
- protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
- /* Error occured during protocol */
- silc_protocol_cancel(protocol, client->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(ctx->sock);
- silc_free(ctx);
- return;
- }
-
- /* Purge the outgoing data queue to assure that all rekey packets really
- go to the network before we quit the protocol. */
- silc_client_packet_queue_purge(client, sock);
-
- /* Re-register re-key timeout */
- if (ctx->responder == FALSE)
- silc_schedule_task_add(client->schedule, sock->sock,
- silc_client_rekey_callback,
- sock, conn->internal->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(ctx->sock);
- silc_free(ctx);
-}
-
-/* Processes incoming connection authentication method request packet.
- It is a reply to our previously sent request. The packet can be used
- to resolve the authentication method for the current session if the
- client does not know it beforehand. */
-
-void silc_client_connection_auth_request(SilcClient client,
- SilcClientConnection conn,
- SilcPacketContext *packet)
-{
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcUInt16 conn_type, auth_meth;
- int ret;
-
- /* If we haven't send our request then ignore this one. */
- if (!conn->internal->connauth)
- return;
-
- /* Parse the payload */
- ret = silc_buffer_unformat(packet->buffer,
- SILC_STR_UI_SHORT(&conn_type),
- SILC_STR_UI_SHORT(&auth_meth),
- SILC_STR_END);
- if (ret == -1)
- auth_meth = SILC_AUTH_NONE;
-
- /* Call the request callback to notify application for received
- authentication method information. */
- if (conn->internal->connauth->callback)
- (*conn->internal->connauth->callback)(client, conn, auth_meth,
- conn->internal->connauth->context);
-
- silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
-
- silc_free(conn->internal->connauth);
- conn->internal->connauth = NULL;
-}
-
-/* Timeout task callback called if the server does not reply to our
- connection authentication method request in the specified time interval. */
-
-SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
-{
- SilcClientConnection conn = (SilcClientConnection)context;
- SilcClient client = conn->client;
-
- if (!conn->internal->connauth)
- return;
-
- /* Call the request callback to notify application */
- if (conn->internal->connauth->callback)
- (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
- conn->internal->connauth->context);
-
- silc_free(conn->internal->connauth);
- conn->internal->connauth = NULL;
-}
-
-/* This function can be used to request the current authentication method
- from the server. This may be called when connecting to the server
- and the client library requests the authentication data from the
- application. If the application does not know the current authentication
- method it can request it from the server using this function.
- The `callback' with `context' will be called after the server has
- replied back with the current authentication method. */
-
-void
-silc_client_request_authentication_method(SilcClient client,
- SilcClientConnection conn,
- SilcConnectionAuthRequest callback,
- void *context)
-{
- SilcClientConnAuthRequest connauth;
- SilcBuffer packet;
-
- assert(client && conn);
- connauth = silc_calloc(1, sizeof(*connauth));
- connauth->callback = callback;
- connauth->context = context;
-
- if (conn->internal->connauth)
- silc_free(conn->internal->connauth);
-
- conn->internal->connauth = connauth;
-
- /* Assemble the request packet and send it to the server */
- packet = silc_buffer_alloc(4);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
- silc_buffer_format(packet,
- SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
- SILC_STR_UI_SHORT(SILC_AUTH_NONE),
- SILC_STR_END);
- silc_client_packet_send(client, conn->sock,
- SILC_PACKET_CONNECTION_AUTH_REQUEST,
- NULL, 0, NULL, NULL,
- packet->data, packet->len, FALSE);
- silc_buffer_free(packet);
-
- /* Register a timeout in case server does not reply anything back. */
- connauth->timeout =
- silc_schedule_task_add(client->schedule, conn->sock->sock,
- silc_client_request_authentication_method_timeout,
- conn,
- client->internal->params->connauth_request_secs, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-}
-#endif /* 0 */
-
-
-/******************************* Client API *********************************/
-