X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient.c;h=745cb698b52daf343e7233769ab7df0f770f7c00;hp=fd0e87bc759478fc464381dc7e555d0fdc60b252;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=4919aeec48375cf8954b53b88dcf7b0d6761c2e1 diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index fd0e87bc..745cb698 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -18,14 +18,14 @@ */ /* $Id$ */ -#include "clientlibincludes.h" +#include "silcincludes.h" +#include "silcclient.h" #include "client_internal.h" /* Static task callback prototypes */ SILC_TASK_CALLBACK(silc_client_connect_to_server_start); SILC_TASK_CALLBACK(silc_client_connect_to_server_second); SILC_TASK_CALLBACK(silc_client_connect_to_server_final); -SILC_TASK_CALLBACK(silc_client_rekey_callback); SILC_TASK_CALLBACK(silc_client_rekey_final); static bool silc_client_packet_parse(SilcPacketParserContext *parser_context, @@ -36,7 +36,7 @@ static void silc_client_packet_parse_type(SilcClient client, void silc_client_resolve_auth_method(bool success, SilcProtocolAuthMeth auth_meth, const unsigned char *auth_data, - uint32 auth_data_len, void *context); + SilcUInt32 auth_data_len, void *context); /* Allocates new client object. This has to be done before client may work. After calling this one must call silc_client_init to initialize @@ -46,7 +46,7 @@ void silc_client_resolve_auth_method(bool success, SilcClient silc_client_alloc(SilcClientOperations *ops, SilcClientParams *params, void *application, - const char *silc_version) + const char *version_string) { SilcClient new_client; @@ -57,7 +57,9 @@ SilcClient silc_client_alloc(SilcClientOperations *ops, new_client->internal->ops = ops; new_client->internal->params = silc_calloc(1, sizeof(*new_client->internal->params)); - new_client->internal->silc_client_version = strdup(silc_version); + if (!version_string) + version_string = silc_version_string; + new_client->internal->silc_client_version = strdup(version_string); if (params) memcpy(new_client->internal->params, params, sizeof(*params)); @@ -86,6 +88,16 @@ void silc_client_free(SilcClient client) if (client->rng) silc_rng_free(client->rng); + silc_cipher_unregister_all(); + silc_pkcs_unregister_all(); + silc_hash_unregister_all(); + silc_hmac_unregister_all(); + + silc_hash_free(client->md5hash); + silc_hash_free(client->sha1hash); + silc_hmac_free(client->internal->md5hmac); + silc_hmac_free(client->internal->sha1hmac); + silc_cipher_free(client->internal->none_cipher); silc_free(client->internal->params); silc_free(client->internal->silc_client_version); silc_free(client->internal); @@ -97,13 +109,26 @@ void silc_client_free(SilcClient client) the client ready to be run. One must call silc_client_run to run the client. Returns FALSE if error occured, TRUE otherwise. */ -int silc_client_init(SilcClient client) +bool silc_client_init(SilcClient client) { SILC_LOG_DEBUG(("Initializing client")); + assert(client); + assert(client->username); + assert(client->hostname); + assert(client->realname); + + /* Initialize the crypto library. If application has done this already + this has no effect. Also, we will not be overriding something + application might have registered earlier. */ + silc_cipher_register_default(); + silc_pkcs_register_default(); + silc_hash_register_default(); + silc_hmac_register_default(); + /* Initialize hash functions for client to use */ - silc_hash_alloc("md5", &client->internal->md5hash); - silc_hash_alloc("sha1", &client->internal->sha1hash); + silc_hash_alloc("md5", &client->md5hash); + silc_hash_alloc("sha1", &client->sha1hash); /* Initialize none cipher */ silc_cipher_alloc("none", &client->internal->none_cipher); @@ -119,7 +144,7 @@ int silc_client_init(SilcClient client) /* Initialize the scheduler */ client->schedule = silc_schedule_init(client->internal->params->task_max ? - client->internal->params->task_max : 200); + client->internal->params->task_max : 200, client); if (!client->schedule) return FALSE; @@ -152,6 +177,11 @@ void silc_client_run(SilcClient client) { SILC_LOG_DEBUG(("Running client")); + assert(client); + assert(client->pkcs); + assert(client->public_key); + assert(client->private_key); + /* Start the scheduler, the heart of the SILC client. When this returns the program will be terminated. */ silc_schedule(client->schedule); @@ -185,27 +215,38 @@ static void silc_client_entry_destructor(SilcIDCache cache, application performed the connecting outside the library. The library however may use this internally. */ -SilcClientConnection silc_client_add_connection(SilcClient client, - char *hostname, - int port, - void *context) +SilcClientConnection +silc_client_add_connection(SilcClient client, + SilcClientConnectionParams *params, + char *hostname, int port, void *context) { SilcClientConnection conn; int i; + SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port)); + conn = silc_calloc(1, sizeof(*conn)); + conn->internal = silc_calloc(1, sizeof(*conn->internal)); /* Initialize ID caches */ - conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, - silc_client_entry_destructor); - conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL); - conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL); conn->client = client; conn->remote_host = strdup(hostname); conn->remote_port = port; conn->context = context; - conn->pending_commands = silc_dlist_init(); - conn->ftp_sessions = silc_dlist_init(); + conn->internal->client_cache = + silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor); + conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL); + conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL); + conn->internal->pending_commands = silc_dlist_init(); + conn->internal->ftp_sessions = silc_dlist_init(); + + if (params) { + if (params->detach_data) + conn->internal->params.detach_data = + silc_memdup(params->detach_data, + params->detach_data_len); + conn->internal->params.detach_data_len = params->detach_data_len; + } /* Add the connection to connections table */ for (i = 0; i < client->internal->conns_count; i++) @@ -231,14 +272,79 @@ void silc_client_del_connection(SilcClient client, SilcClientConnection conn) for (i = 0; i < client->internal->conns_count; i++) if (client->internal->conns[i] == conn) { + /* Free all cache entries */ + SilcIDCacheList list; + SilcIDCacheEntry entry; + SilcClientCommandPending *r; + bool ret; + + if (silc_idcache_get_all(conn->internal->client_cache, &list)) { + ret = silc_idcache_list_first(list, &entry); + while (ret) { + silc_client_del_client(client, conn, entry->context); + ret = silc_idcache_list_next(list, &entry); + } + silc_idcache_list_free(list); + } - silc_idcache_free(conn->client_cache); - silc_idcache_free(conn->channel_cache); - silc_idcache_free(conn->server_cache); - if (conn->pending_commands) - silc_dlist_uninit(conn->pending_commands); + if (silc_idcache_get_all(conn->internal->channel_cache, &list)) { + ret = silc_idcache_list_first(list, &entry); + while (ret) { + silc_client_del_channel(client, conn, entry->context); + ret = silc_idcache_list_next(list, &entry); + } + silc_idcache_list_free(list); + } + + if (silc_idcache_get_all(conn->internal->server_cache, &list)) { + ret = silc_idcache_list_first(list, &entry); + while (ret) { + silc_client_del_server(client, conn, entry->context); + ret = silc_idcache_list_next(list, &entry); + } + silc_idcache_list_free(list); + } + + /* Clear ID caches */ + if (conn->internal->client_cache) + silc_idcache_free(conn->internal->client_cache); + if (conn->internal->channel_cache) + silc_idcache_free(conn->internal->channel_cache); + if (conn->internal->server_cache) + silc_idcache_free(conn->internal->server_cache); + + /* Free data (my ID is freed in above silc_client_del_client). + conn->nickname is freed when freeing the local_entry->nickname. */ silc_free(conn->remote_host); - silc_dlist_uninit(conn->ftp_sessions); + silc_free(conn->local_id_data); + if (conn->internal->send_key) + silc_cipher_free(conn->internal->send_key); + if (conn->internal->receive_key) + silc_cipher_free(conn->internal->receive_key); + if (conn->internal->hmac_send) + silc_hmac_free(conn->internal->hmac_send); + if (conn->internal->hmac_receive) + silc_hmac_free(conn->internal->hmac_receive); + silc_free(conn->internal->rekey); + + if (conn->internal->active_session) { + conn->sock->user_data = NULL; + silc_client_ftp_session_free(conn->internal->active_session); + conn->internal->active_session = NULL; + } + + silc_client_ftp_free_sessions(client, conn); + + if (conn->internal->pending_commands) { + silc_dlist_start(conn->internal->pending_commands); + while ((r = silc_dlist_get(conn->internal->pending_commands)) + != SILC_LIST_END) + silc_dlist_del(conn->internal->pending_commands, r); + silc_dlist_uninit(conn->internal->pending_commands); + } + + silc_free(conn->internal); + memset(conn, 0, sizeof(*conn)); silc_free(conn); client->internal->conns[i] = NULL; @@ -314,7 +420,8 @@ silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx) (void *)ctx, 0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL); - silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE); + silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE, + FALSE); ctx->sock = sock; @@ -329,8 +436,9 @@ silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx) case then this function is not used at all. When the connecting is done the `connect' client operation is called. */ -int silc_client_connect_to_server(SilcClient client, int port, - char *host, void *context) +bool silc_client_connect_to_server(SilcClient client, + SilcClientConnectionParams *params, + int port, char *host, void *context) { SilcClientInternalConnectContext *ctx; SilcClientConnection conn; @@ -339,7 +447,7 @@ int silc_client_connect_to_server(SilcClient client, int port, SILC_LOG_DEBUG(("Connecting to port %d of server %s", port, host)); - conn = silc_client_add_connection(client, host, port, context); + conn = silc_client_add_connection(client, params, host, port, context); client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, "Connecting to port %d of server %s", port, host); @@ -350,7 +458,7 @@ int silc_client_connect_to_server(SilcClient client, int port, ctx->client = client; ctx->conn = conn; ctx->host = strdup(host); - ctx->port = port; + ctx->port = port ? port : 706; ctx->tries = 0; /* Do the actual connecting process */ @@ -374,12 +482,14 @@ static void silc_client_start_key_exchange_cb(SilcSocketConnection sock, SILC_LOG_DEBUG(("Start")); - /* XXX We should most likely use the resolved host name instead of the - one user provided for us. */ - silc_free(conn->sock->hostname); - conn->sock->hostname = strdup(conn->remote_host); + if (conn->sock->hostname) { + silc_free(conn->remote_host); + conn->remote_host = strdup(conn->sock->hostname); + } else { + conn->sock->hostname = strdup(conn->remote_host); + } if (!conn->sock->ip) - conn->sock->ip = strdup(conn->remote_host); + conn->sock->ip = strdup(conn->sock->hostname); conn->sock->port = conn->remote_port; /* Allocate internal Key Exchange context. This is sent to the @@ -401,7 +511,7 @@ static void silc_client_start_key_exchange_cb(SilcSocketConnection sock, client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, "Error: Could not start key exchange protocol"); silc_net_close_connection(conn->sock->sock); - client->internal->ops->connect(client, conn, FALSE); + client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR); return; } conn->sock->protocol = protocol; @@ -430,6 +540,10 @@ void silc_client_start_key_exchange(SilcClient client, SilcClientConnection conn, int fd) { + assert(client->pkcs); + assert(client->public_key); + assert(client->private_key); + /* Allocate new socket connection object */ silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock); @@ -447,8 +561,8 @@ void silc_client_start_key_exchange(SilcClient client, conn, client->schedule); } -/* Callback called when error has occurred during connecting to the server. - The `connect' client operation will be called. */ +/* Callback called when error has occurred during connecting (KE) to + the server. The `connect' client operation will be called. */ SILC_TASK_CALLBACK(silc_client_connect_failure) { @@ -456,7 +570,24 @@ SILC_TASK_CALLBACK(silc_client_connect_failure) (SilcClientKEInternalContext *)context; SilcClient client = (SilcClient)ctx->client; - client->internal->ops->connect(client, ctx->sock->user_data, FALSE); + client->internal->ops->connected(client, ctx->sock->user_data, + SILC_CLIENT_CONN_ERROR); + if (ctx->packet) + silc_packet_context_free(ctx->packet); + silc_free(ctx); +} + +/* Callback called when error has occurred during connecting (auth) to + the server. The `connect' client operation will be called. */ + +SILC_TASK_CALLBACK(silc_client_connect_failure_auth) +{ + SilcClientConnAuthInternalContext *ctx = + (SilcClientConnAuthInternalContext *)context; + SilcClient client = (SilcClient)ctx->client; + + client->internal->ops->connected(client, ctx->sock->user_data, + SILC_CLIENT_CONN_ERROR); silc_free(ctx); } @@ -504,7 +635,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start) silc_free(ctx); /* Notify application of failure */ - client->internal->ops->connect(client, conn, FALSE); + client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR); silc_client_del_connection(client, conn); } return; @@ -576,6 +707,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second) silc_protocol_free(protocol); if (ctx->packet) silc_packet_context_free(ctx->packet); + ctx->packet = NULL; silc_free(ctx); sock->protocol = NULL; @@ -597,7 +729,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second) void silc_client_resolve_auth_method(bool success, SilcProtocolAuthMeth auth_meth, const unsigned char *auth_data, - uint32 auth_data_len, void *context) + SilcUInt32 auth_data_len, void *context) { SilcClientConnAuthInternalContext *proto_ctx = (SilcClientConnAuthInternalContext *)context; @@ -608,9 +740,22 @@ void silc_client_resolve_auth_method(bool success, proto_ctx->auth_meth = auth_meth; - if (auth_data && auth_data_len) { - proto_ctx->auth_data = silc_calloc(auth_data_len, sizeof(*auth_data)); - memcpy(proto_ctx->auth_data, auth_data, auth_data_len); + if (success && auth_data && auth_data_len) { + + /* Passphrase must be UTF-8 encoded, if it isn't encode it */ + if (auth_meth == SILC_AUTH_PASSWORD && + !silc_utf8_valid(auth_data, auth_data_len)) { + int payload_len = 0; + unsigned char *autf8 = NULL; + payload_len = silc_utf8_encoded_len(auth_data, auth_data_len, + SILC_STRING_ASCII); + autf8 = silc_calloc(payload_len, sizeof(*autf8)); + auth_data_len = silc_utf8_encode(auth_data, auth_data_len, + SILC_STRING_ASCII, autf8, payload_len); + auth_data = autf8; + } + + proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len); proto_ctx->auth_data_len = auth_data_len; } @@ -643,43 +788,75 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final) protocol->state == SILC_PROTOCOL_STATE_FAILURE) { /* Error occured during protocol */ SILC_LOG_DEBUG(("Error during authentication protocol")); - silc_protocol_free(protocol); - if (ctx->auth_data) - silc_free(ctx->auth_data); - if (ctx->ske) - silc_ske_free(ctx->ske); - if (ctx->dest_id) - silc_free(ctx->dest_id); - conn->sock->protocol = NULL; - silc_socket_free(ctx->sock); - - /* Notify application of failure */ - silc_schedule_task_add(client->schedule, ctx->sock->sock, - silc_client_connect_failure, ctx, - 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); - return; + goto err; } - /* Send NEW_CLIENT packet to the server. We will become registered - to the SILC network after sending this packet and we will receive - client ID from the server. */ - packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + - strlen(client->realname)); - silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); - silc_buffer_format(packet, - SILC_STR_UI_SHORT(strlen(client->username)), - SILC_STR_UI_XNSTRING(client->username, - strlen(client->username)), - SILC_STR_UI_SHORT(strlen(client->realname)), - SILC_STR_UI_XNSTRING(client->realname, - strlen(client->realname)), - SILC_STR_END); + if (conn->internal->params.detach_data) { + /* Send RESUME_CLIENT packet to the server, which is used to resume + old detached session back. */ + SilcBuffer auth; + SilcClientID *old_client_id; + unsigned char *old_id; + SilcUInt16 old_id_len; + + if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len)) + goto err; + + old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT); + if (!old_client_id) { + silc_free(old_id); + goto err; + } - /* Send the packet */ - silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT, - NULL, 0, NULL, NULL, - packet->data, packet->len, TRUE); - silc_buffer_free(packet); + /* Generate authentication data that server will verify */ + auth = silc_auth_public_key_auth_generate(client->public_key, + client->private_key, + client->rng, + conn->internal->hash, + old_client_id, SILC_ID_CLIENT); + if (!auth) { + silc_free(old_client_id); + silc_free(old_id); + goto err; + } + + packet = silc_buffer_alloc_size(2 + old_id_len + auth->len); + silc_buffer_format(packet, + SILC_STR_UI_SHORT(old_id_len), + SILC_STR_UI_XNSTRING(old_id, old_id_len), + SILC_STR_UI_XNSTRING(auth->data, auth->len), + SILC_STR_END); + + /* Send the packet */ + silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT, + NULL, 0, NULL, NULL, + packet->data, packet->len, TRUE); + silc_buffer_free(packet); + silc_buffer_free(auth); + silc_free(old_client_id); + silc_free(old_id); + } else { + /* Send NEW_CLIENT packet to the server. We will become registered + to the SILC network after sending this packet and we will receive + client ID from the server. */ + packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + + strlen(client->realname)); + silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); + silc_buffer_format(packet, + SILC_STR_UI_SHORT(strlen(client->username)), + SILC_STR_UI_XNSTRING(client->username, + strlen(client->username)), + SILC_STR_UI_SHORT(strlen(client->realname)), + SILC_STR_UI_XNSTRING(client->realname, + strlen(client->realname)), + SILC_STR_END); + + /* Send the packet */ + silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT, + NULL, 0, NULL, NULL, + packet->data, packet->len, TRUE); + silc_buffer_free(packet); + } /* Save remote ID. */ conn->remote_id = ctx->dest_id; @@ -687,28 +864,42 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final) conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER); /* Register re-key timeout */ - conn->rekey->timeout = client->internal->params->rekey_secs; - conn->rekey->context = (void *)client; + conn->internal->rekey->timeout = client->internal->params->rekey_secs; + conn->internal->rekey->context = (void *)client; silc_schedule_task_add(client->schedule, conn->sock->sock, silc_client_rekey_callback, - (void *)conn->sock, conn->rekey->timeout, 0, + (void *)conn->sock, conn->internal->rekey->timeout, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); silc_protocol_free(protocol); - if (ctx->auth_data) - silc_free(ctx->auth_data); + silc_free(ctx->auth_data); if (ctx->ske) silc_ske_free(ctx->ske); silc_socket_free(ctx->sock); silc_free(ctx); conn->sock->protocol = NULL; + return; + + err: + silc_protocol_free(protocol); + silc_free(ctx->auth_data); + silc_free(ctx->dest_id); + if (ctx->ske) + silc_ske_free(ctx->ske); + conn->sock->protocol = NULL; + silc_socket_free(ctx->sock); + + /* Notify application of failure */ + silc_schedule_task_add(client->schedule, ctx->sock->sock, + silc_client_connect_failure_auth, ctx, + 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); } /* Internal routine that sends packet or marks packet to be sent. This is used directly only in special cases. Normal cases should use silc_server_packet_send. Returns < 0 on error. */ -int silc_client_packet_send_real(SilcClient client, +bool silc_client_packet_send_real(SilcClient client, SilcSocketConnection sock, bool force_send) { @@ -766,9 +957,6 @@ SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process) if (SILC_IS_DISCONNECTED(sock)) return; - if (sock->outbuf->data - sock->outbuf->head) - silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head); - ret = silc_packet_send(sock, TRUE); /* If returned -2 could not write to connection now, will do @@ -806,23 +994,24 @@ SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process) close the connection */ if (SILC_IS_DISCONNECTING(sock)) { if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT) - client->internal->ops->disconnect(client, conn); - silc_client_close_connection(client, sock, conn); + client->internal->ops->disconnected(client, conn, 0, NULL); + silc_client_close_connection_real(client, sock, conn); return; } SILC_LOG_DEBUG(("EOF from connection %d", sock->sock)); if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT) - client->internal->ops->disconnect(client, conn); - silc_client_close_connection(client, sock, conn); + client->internal->ops->disconnected(client, conn, 0, NULL); + silc_client_close_connection_real(client, sock, conn); return; } /* Process the packet. This will call the parser that will then decrypt and parse the packet. */ if (sock->type != SILC_SOCKET_TYPE_UNKNOWN) - silc_packet_receive_process(sock, FALSE, conn->receive_key, - conn->hmac_receive, conn->psn_receive, + silc_packet_receive_process(sock, FALSE, conn->internal->receive_key, + conn->internal->hmac_receive, + conn->internal->psn_receive, silc_client_packet_parse, client); else silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, @@ -842,14 +1031,14 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context, SilcPacketContext *packet = parser_context->packet; SilcPacketType ret; - if (conn && conn->hmac_receive && conn->sock == sock) - conn->psn_receive = parser_context->packet->sequence + 1; + if (conn && conn->internal->hmac_receive && conn->sock == sock) + conn->internal->psn_receive = parser_context->packet->sequence + 1; /* Parse the packet immediately */ if (parser_context->normal) - ret = silc_packet_parse(packet, conn->receive_key); + ret = silc_packet_parse(packet, conn->internal->receive_key); else - ret = silc_packet_parse_special(packet, conn->receive_key); + ret = silc_packet_parse_special(packet, conn->internal->receive_key); if (ret == SILC_PACKET_NONE) { silc_packet_context_free(packet); @@ -872,11 +1061,12 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context, silc_free(parser_context); /* Reprocess the buffer since we'll return FALSE. This is because - the `conn->receive_key' might have become valid by processing + the `conn->internal->receive_key' might have become valid by processing the previous packet */ if (sock->type != SILC_SOCKET_TYPE_UNKNOWN) - silc_packet_receive_process(sock, FALSE, conn->receive_key, - conn->hmac_receive, conn->psn_receive, + silc_packet_receive_process(sock, FALSE, conn->internal->receive_key, + conn->internal->hmac_receive, + conn->internal->psn_receive, silc_client_packet_parse, client); else silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, @@ -902,13 +1092,15 @@ void silc_client_packet_parse_type(SilcClient client, SilcBuffer buffer = packet->buffer; SilcPacketType type = packet->type; - SILC_LOG_DEBUG(("Parsing packet type %d", type)); + SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type))); /* Parse the packet type */ switch(type) { + case SILC_PACKET_DISCONNECT: silc_client_disconnected_by_server(client, sock, buffer); break; + case SILC_PACKET_SUCCESS: /* * Success received for something. For now we can have only @@ -918,6 +1110,7 @@ void silc_client_packet_parse_type(SilcClient client, if (sock->protocol) silc_protocol_execute(sock->protocol, client->schedule, 0, 0); break; + case SILC_PACKET_FAILURE: /* * Failure received for some protocol. Set the protocol state to @@ -926,6 +1119,7 @@ void silc_client_packet_parse_type(SilcClient client, */ silc_client_process_failure(client, sock, packet); break; + case SILC_PACKET_REJECT: break; @@ -949,6 +1143,7 @@ void silc_client_packet_parse_type(SilcClient client, */ silc_client_channel_message(client, sock, packet); break; + case SILC_PACKET_CHANNEL_KEY: /* * Received key for a channel. By receiving this key the client will be @@ -964,12 +1159,21 @@ void silc_client_packet_parse_type(SilcClient client, */ silc_client_private_message(client, sock, packet); break; + case SILC_PACKET_PRIVATE_MESSAGE_KEY: /* * Received private message key */ break; + case SILC_PACKET_COMMAND: + /* + * Received command packet, a special case since normally client + * does not receive commands. + */ + silc_client_command_process(client, sock, packet); + break; + case SILC_PACKET_COMMAND_REPLY: /* * Recived reply for a command @@ -1036,6 +1240,7 @@ void silc_client_packet_parse_type(SilcClient client, "protocol active, packet dropped.")); } break; + case SILC_PACKET_KEY_EXCHANGE_2: if (sock->protocol && sock->protocol->protocol && (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE || @@ -1058,7 +1263,8 @@ void silc_client_packet_parse_type(SilcClient client, if (proto_ctx->packet) silc_packet_context_free(proto_ctx->packet); - + if (proto_ctx->dest_id) + silc_free(proto_ctx->dest_id); proto_ctx->packet = silc_packet_context_dup(packet); proto_ctx->dest_id_type = packet->src_id_type; proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len, @@ -1177,12 +1383,13 @@ void silc_client_packet_send(SilcClient client, SilcCipher cipher, SilcHmac hmac, unsigned char *data, - uint32 data_len, - int force_send) + SilcUInt32 data_len, + bool force_send) { SilcPacketContext packetdata; + const SilcBufferStruct packet; int block_len; - uint32 sequence = 0; + SilcUInt32 sequence = 0; if (!sock) return; @@ -1191,11 +1398,11 @@ void silc_client_packet_send(SilcClient client, /* Get data used in the packet sending, keys and stuff */ if ((!cipher || !hmac || !dst_id) && sock->user_data) { - if (!cipher && ((SilcClientConnection)sock->user_data)->send_key) - cipher = ((SilcClientConnection)sock->user_data)->send_key; + if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key) + cipher = ((SilcClientConnection)sock->user_data)->internal->send_key; - if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send) - hmac = ((SilcClientConnection)sock->user_data)->hmac_send; + if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send) + hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send; if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) { dst_id = ((SilcClientConnection)sock->user_data)->remote_id; @@ -1203,7 +1410,13 @@ void silc_client_packet_send(SilcClient client, } if (hmac) - sequence = ((SilcClientConnection)sock->user_data)->psn_send++; + sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++; + + /* Check for mandatory rekey */ + if (sequence == SILC_CLIENT_REKEY_THRESHOLD) + silc_schedule_task_add(client->schedule, sock->sock, + silc_client_rekey_callback, sock, 0, 1, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); } block_len = cipher ? silc_cipher_get_block_len(cipher) : 0; @@ -1231,51 +1444,60 @@ void silc_client_packet_send(SilcClient client, packetdata.dst_id_len = 0; packetdata.dst_id_type = SILC_ID_NONE; } + data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN + + packetdata.src_id_len + + packetdata.dst_id_len)); packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + packetdata.src_id_len + packetdata.dst_id_len; - packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len); - - /* Prepare outgoing data buffer for packet sending */ - silc_packet_send_prepare(sock, - SILC_PACKET_HEADER_LEN + - packetdata.src_id_len + - packetdata.dst_id_len, - packetdata.padlen, - data_len); - - SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len)); - - packetdata.buffer = sock->outbuf; - - /* Put the data to the buffer */ - if (data && data_len) - silc_buffer_put(sock->outbuf, data, data_len); + if (type == SILC_PACKET_CONNECTION_AUTH) + SILC_PACKET_PADLEN_MAX(packetdata.truelen, block_len, packetdata.padlen); + else + SILC_PACKET_PADLEN(packetdata.truelen, block_len, packetdata.padlen); /* Create the outgoing packet */ - silc_packet_assemble(&packetdata, cipher); + if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, + data, data_len, (const SilcBuffer)&packet)) { + SILC_LOG_ERROR(("Error assembling packet")); + return; + } /* Encrypt the packet */ if (cipher) - silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, - sock->outbuf->len); + silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, + packet.len); - SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, sock->outbuf->len), - sock->outbuf->data, sock->outbuf->len); + SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len), + packet.data, packet.len); /* Now actually send the packet */ silc_client_packet_send_real(client, sock, force_send); } +/* Packet sending routine for application. This is the only routine that + is provided for application to send SILC packets. */ + +bool silc_client_send_packet(SilcClient client, + SilcClientConnection conn, + SilcPacketType type, + const unsigned char *data, + SilcUInt32 data_len) +{ + + assert(client); + if (!conn) + return FALSE; + + silc_client_packet_send(client, conn->sock, type, NULL, 0, NULL, NULL, + (unsigned char *)data, data_len, TRUE); + return TRUE; +} + void silc_client_packet_queue_purge(SilcClient client, SilcSocketConnection sock) { if (sock && SILC_IS_OUTBUF_PENDING(sock) && (SILC_IS_DISCONNECTED(sock) == FALSE)) { - if (sock->outbuf->data - sock->outbuf->head) - silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head); - silc_packet_send(sock, TRUE); - SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock); SILC_UNSET_OUTBUF_PENDING(sock); silc_buffer_clear(sock->outbuf); @@ -1290,14 +1512,17 @@ void silc_client_packet_queue_purge(SilcClient client, connection but `conn->sock' might be actually a different connection than the `sock'). */ -void silc_client_close_connection(SilcClient client, - SilcSocketConnection sock, - SilcClientConnection conn) +void silc_client_close_connection_real(SilcClient client, + SilcSocketConnection sock, + SilcClientConnection conn) { int del = FALSE; SILC_LOG_DEBUG(("Start")); + if (!sock && !conn) + return; + if (!sock || (sock && conn->sock == sock)) del = TRUE; if (!sock) @@ -1308,7 +1533,6 @@ void silc_client_close_connection(SilcClient client, /* Unregister all tasks */ silc_schedule_task_del_by_fd(client->schedule, sock->sock); - silc_schedule_task_del_by_fd(client->schedule, sock->sock); /* Close the actual connection */ silc_net_close_connection(sock->sock); @@ -1322,7 +1546,7 @@ void silc_client_close_connection(SilcClient client, sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; silc_protocol_execute_final(sock->protocol, client->schedule); /* The application will recall this function with these protocols - (the ops->connect client operation). */ + (the ops->connected client operation). */ return; } else { sock->protocol->state = SILC_PROTOCOL_STATE_ERROR; @@ -1332,80 +1556,20 @@ void silc_client_close_connection(SilcClient client, } /* Free everything */ - if (del && sock->user_data) { - /* Free all cache entries */ - SilcIDCacheList list; - SilcIDCacheEntry entry; - bool ret; - - if (silc_idcache_get_all(conn->client_cache, &list)) { - ret = silc_idcache_list_first(list, &entry); - while (ret) { - silc_client_del_client(client, conn, entry->context); - ret = silc_idcache_list_next(list, &entry); - } - silc_idcache_list_free(list); - } - - if (silc_idcache_get_all(conn->channel_cache, &list)) { - ret = silc_idcache_list_first(list, &entry); - while (ret) { - silc_client_del_channel(client, conn, entry->context); - ret = silc_idcache_list_next(list, &entry); - } - silc_idcache_list_free(list); - } - - if (silc_idcache_get_all(conn->server_cache, &list)) { - ret = silc_idcache_list_first(list, &entry); - while (ret) { - silc_client_del_server(client, conn, entry->context); - ret = silc_idcache_list_next(list, &entry); - } - silc_idcache_list_free(list); - } - - /* Clear ID caches */ - if (conn->client_cache) - silc_idcache_del_all(conn->client_cache); - if (conn->channel_cache) - silc_idcache_del_all(conn->channel_cache); - if (conn->server_cache) - silc_idcache_del_all(conn->server_cache); - - /* Free data (my ID is freed in above silc_client_del_client) */ - if (conn->remote_host) - silc_free(conn->remote_host); - if (conn->local_id_data) - silc_free(conn->local_id_data); - if (conn->send_key) - silc_cipher_free(conn->send_key); - if (conn->receive_key) - silc_cipher_free(conn->receive_key); - if (conn->hmac_send) - silc_hmac_free(conn->hmac_send); - if (conn->hmac_receive) - silc_hmac_free(conn->hmac_receive); - if (conn->pending_commands) - silc_dlist_uninit(conn->pending_commands); - if (conn->rekey) - silc_free(conn->rekey); - - if (conn->active_session) { - sock->user_data = NULL; - silc_client_ftp_session_free(conn->active_session); - conn->active_session = NULL; - } - - silc_client_ftp_free_sessions(client, conn); - - memset(conn, 0, sizeof(*conn)); + if (del && sock->user_data) silc_client_del_connection(client, conn); - } silc_socket_free(sock); } +/* Closes the connection to the remote end */ + +void silc_client_close_connection(SilcClient client, + SilcClientConnection conn) +{ + silc_client_close_connection_real(client, NULL, conn); +} + /* Called when we receive disconnection packet from server. This closes our end properly and displays the reason of the disconnection on the screen. */ @@ -1419,7 +1583,7 @@ SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later) if (sock == NULL) return; - silc_client_close_connection(client, sock, sock->user_data); + silc_client_close_connection_real(client, sock, sock->user_data); } /* Called when we receive disconnection packet from server. This @@ -1428,17 +1592,28 @@ SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later) void silc_client_disconnected_by_server(SilcClient client, SilcSocketConnection sock, - SilcBuffer message) + SilcBuffer packet) { - char *msg; + SilcClientConnection conn; + SilcStatus status; + char *message = NULL; SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock)); - msg = silc_calloc(message->len + 1, sizeof(char)); - memcpy(msg, message->data, message->len); - client->internal->ops->say(client, sock->user_data, - SILC_CLIENT_MESSAGE_AUDIT, msg); - silc_free(msg); + if (packet->len < 1) + return; + + status = (SilcStatus)packet->data[0]; + + if (packet->len > 1 && + silc_utf8_valid(packet->data + 1, packet->len - 1)) + message = silc_memdup(packet->data + 1, packet->len - 1); + + conn = (SilcClientConnection)sock->user_data; + if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT) + client->internal->ops->disconnected(client, conn, status, message); + + silc_free(message); SILC_SET_DISCONNECTED(sock); @@ -1458,13 +1633,54 @@ void silc_client_error_by_server(SilcClient client, { char *msg; - msg = silc_calloc(message->len + 1, sizeof(char)); - memcpy(msg, message->data, message->len); + msg = silc_memdup(message->data, message->len); client->internal->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg); silc_free(msg); } +/* Auto-nicking callback to send NICK command to server. */ + +SILC_TASK_CALLBACK(silc_client_send_auto_nick) +{ + SilcClientConnection conn = (SilcClientConnection)context; + SilcClient client = conn->client; + if (client) + silc_client_command_send(client, conn, SILC_COMMAND_NICK, + ++conn->cmd_ident, 1, 1, + client->nickname, strlen(client->nickname)); +} + +/* Client session resuming callback. If the session was resumed + this callback is called after the resuming is completed. This + will call the `connect' client operation to the application + since it has not been called yet. */ + +static void silc_client_resume_session_cb(SilcClient client, + SilcClientConnection conn, + bool success, + void *context) +{ + SilcBuffer sidp; + + /* Notify application that connection is created to server */ + client->internal->ops->connected(client, conn, success ? + SILC_CLIENT_CONN_SUCCESS_RESUME : + SILC_CLIENT_CONN_ERROR); + + if (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); + } +} + /* Processes the received new Client ID from server. Old Client ID is deleted from cache and new one is added. */ @@ -1475,7 +1691,6 @@ void silc_client_receive_new_id(SilcClient client, SilcClientConnection conn = (SilcClientConnection)sock->user_data; int connecting = FALSE; SilcClientID *client_id = silc_id_payload_get_id(idp); - SilcBuffer sidp; if (!conn->local_entry) connecting = TRUE; @@ -1488,7 +1703,8 @@ void silc_client_receive_new_id(SilcClient client, return; } - silc_idcache_del_by_context(conn->client_cache, conn->local_entry); + silc_idcache_del_by_context(conn->internal->client_cache, + conn->local_entry); silc_free(conn->local_id); } @@ -1507,107 +1723,83 @@ void silc_client_receive_new_id(SilcClient client, conn->local_entry->nickname = conn->nickname; if (!conn->local_entry->username) conn->local_entry->username = strdup(client->username); - if (!conn->local_entry->hostname) - conn->local_entry->hostname = strdup(client->hostname); - conn->local_entry->server = strdup(conn->remote_host); + 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); + /* Put it to the ID cache */ - silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, + silc_idcache_add(conn->internal->client_cache, + strdup(conn->nickname), conn->local_id, (void *)conn->local_entry, 0, NULL); if (connecting) { - /* Send NICK command if the nickname was set by the application (and is - not same as the username). */ - if (client->nickname && strcmp(client->nickname, client->username)) - silc_client_command_send(client, conn, SILC_COMMAND_NICK, - ++conn->cmd_ident, 1, 1, - client->nickname, strlen(client->nickname)); - - /* 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, + 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->remote_id, SILC_ID_SERVER); - silc_client_command_send(client, conn, SILC_COMMAND_INFO, - conn->cmd_ident, 1, 2, sidp->data, sidp->len); + 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); - /* 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->connect(client, conn, TRUE); + 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 && strcmp(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); + } } } -/* Processed received Channel ID for a channel. This is called when client - joins to channel and server replies with channel ID. The ID is cached. - Returns the created channel entry. This is also called when received - channel ID in for example USERS command reply that we do not have. */ - -SilcChannelEntry silc_client_new_channel_id(SilcClient client, - SilcSocketConnection sock, - char *channel_name, - uint32 mode, - SilcIDPayload idp) -{ - SilcClientConnection conn = (SilcClientConnection)sock->user_data; - SilcChannelEntry channel; - - SILC_LOG_DEBUG(("New channel ID")); - - channel = silc_calloc(1, sizeof(*channel)); - channel->channel_name = channel_name; - channel->id = silc_id_payload_get_id(idp); - channel->mode = mode; - silc_list_init(channel->clients, struct SilcChannelUserStruct, next); - - /* Put it to the ID cache */ - silc_idcache_add(conn->channel_cache, channel->channel_name, - (void *)channel->id, (void *)channel, 0, NULL); - - return channel; -} - -/* Removes a client entry from all channel it has joined. This really is - a performance killer (client_entry should have pointers to channel - entry list). */ +/* Removes a client entry from all channels it has joined. */ void silc_client_remove_from_channels(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { - SilcIDCacheEntry id_cache; - SilcIDCacheList list; - SilcChannelEntry channel; + SilcHashTableList htl; SilcChannelUser chu; - if (!silc_idcache_get_all(conn->channel_cache, &list)) - return; - - silc_idcache_list_first(list, &id_cache); - channel = (SilcChannelEntry)id_cache->context; - - while (channel) { - - /* Remove client from channel */ - silc_list_start(channel->clients); - while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - if (chu->client == client_entry) { - silc_list_del(channel->clients, chu); - silc_free(chu); - break; - } - } - - if (!silc_idcache_list_next(list, &id_cache)) - break; - - channel = (SilcChannelEntry)id_cache->context; + 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_idcache_list_free(list); + silc_hash_table_list_reset(&htl); } /* Replaces `old' client entries from all channels to `new' client entry. @@ -1620,35 +1812,20 @@ void silc_client_replace_from_channels(SilcClient client, SilcClientEntry old, SilcClientEntry new) { - SilcIDCacheEntry id_cache; - SilcIDCacheList list; - SilcChannelEntry channel; + SilcHashTableList htl; SilcChannelUser chu; - if (!silc_idcache_get_all(conn->channel_cache, &list)) - return; - - silc_idcache_list_first(list, &id_cache); - channel = (SilcChannelEntry)id_cache->context; - - while (channel) { - + silc_hash_table_list(old->channels, &htl); + while (silc_hash_table_get(&htl, NULL, (void **)&chu)) { /* Replace client entry */ - silc_list_start(channel->clients); - while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { - if (chu->client == old) { - chu->client = new; - break; - } - } - - if (!silc_idcache_list_next(list, &id_cache)) - break; + silc_hash_table_del(chu->client->channels, chu->channel); + silc_hash_table_del(chu->channel->user_list, chu->client); - channel = (SilcChannelEntry)id_cache->context; + 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_idcache_list_free(list); + silc_hash_table_list_reset(&htl); } /* Registers failure timeout to process the received failure packet @@ -1658,7 +1835,7 @@ void silc_client_process_failure(SilcClient client, SilcSocketConnection sock, SilcPacketContext *packet) { - uint32 failure = 0; + SilcUInt32 failure = 0; if (sock->protocol) { if (packet->buffer->len >= 4) @@ -1673,11 +1850,11 @@ void silc_client_process_failure(SilcClient client, /* A timeout callback for the re-key. We will be the initiator of the re-key protocol. */ -SILC_TASK_CALLBACK(silc_client_rekey_callback) +SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback) { SilcSocketConnection sock = (SilcSocketConnection)context; SilcClientConnection conn = (SilcClientConnection)sock->user_data; - SilcClient client = (SilcClient)conn->rekey->context; + SilcClient client = (SilcClient)conn->internal->rekey->context; SilcProtocol protocol; SilcClientRekeyInternalContext *proto_ctx; @@ -1689,7 +1866,7 @@ SILC_TASK_CALLBACK(silc_client_rekey_callback) proto_ctx->client = (void *)client; proto_ctx->sock = silc_socket_dup(sock); proto_ctx->responder = FALSE; - proto_ctx->pfs = conn->rekey->pfs; + proto_ctx->pfs = conn->internal->rekey->pfs; /* Perform rekey protocol. Will call the final callback after the protocol is over. */ @@ -1703,7 +1880,7 @@ SILC_TASK_CALLBACK(silc_client_rekey_callback) /* Re-register re-key timeout */ silc_schedule_task_add(client->schedule, sock->sock, silc_client_rekey_callback, - context, conn->rekey->timeout, 0, + context, conn->internal->rekey->timeout, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); } @@ -1760,11 +1937,11 @@ void silc_client_connection_auth_request(SilcClient client, SilcPacketContext *packet) { SilcClientConnection conn = (SilcClientConnection)sock->user_data; - uint16 conn_type, auth_meth; + SilcUInt16 conn_type, auth_meth; int ret; /* If we haven't send our request then ignore this one. */ - if (!conn->connauth) + if (!conn->internal->connauth) return; /* Parse the payload */ @@ -1777,14 +1954,14 @@ void silc_client_connection_auth_request(SilcClient client, /* Call the request callback to notify application for received authentication method information. */ - if (conn->connauth->callback) - (*conn->connauth->callback)(client, conn, auth_meth, - conn->connauth->context); + if (conn->internal->connauth->callback) + (*conn->internal->connauth->callback)(client, conn, auth_meth, + conn->internal->connauth->context); - silc_schedule_task_del(client->schedule, conn->connauth->timeout); + silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout); - silc_free(conn->connauth); - conn->connauth = NULL; + silc_free(conn->internal->connauth); + conn->internal->connauth = NULL; } /* Timeout task callback called if the server does not reply to our @@ -1795,16 +1972,16 @@ SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout) SilcClientConnection conn = (SilcClientConnection)context; SilcClient client = conn->client; - if (!conn->connauth) + if (!conn->internal->connauth) return; /* Call the request callback to notify application */ - if (conn->connauth->callback) - (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE, - conn->connauth->context); + if (conn->internal->connauth->callback) + (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE, + conn->internal->connauth->context); - silc_free(conn->connauth); - conn->connauth = NULL; + silc_free(conn->internal->connauth); + conn->internal->connauth = NULL; } /* This function can be used to request the current authentication method @@ -1824,14 +2001,15 @@ silc_client_request_authentication_method(SilcClient client, SilcClientConnAuthRequest connauth; SilcBuffer packet; + assert(client && conn); connauth = silc_calloc(1, sizeof(*connauth)); connauth->callback = callback; connauth->context = context; - if (conn->connauth) - silc_free(conn->connauth); + if (conn->internal->connauth) + silc_free(conn->internal->connauth); - conn->connauth = connauth; + conn->internal->connauth = connauth; /* Assemble the request packet and send it to the server */ packet = silc_buffer_alloc(4);