Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2003 Pekka Riikonen
+ Copyright (C) 1997 - 2005 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if (client->rng)
silc_rng_free(client->rng);
- silc_cipher_unregister_all();
- silc_pkcs_unregister_all();
- silc_hash_unregister_all();
- silc_hmac_unregister_all();
+ if (!client->internal->params->dont_register_crypto_library) {
+ 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);
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();
+ /* Validate essential strings */
+ if (client->nickname)
+ if (!silc_identifier_verify(client->nickname, strlen(client->nickname),
+ SILC_STRING_UTF8, 128)) {
+ SILC_LOG_ERROR(("Malformed nickname '%s'", client->nickname));
+ return FALSE;
+ }
+ if (!silc_identifier_verify(client->username, strlen(client->username),
+ SILC_STRING_UTF8, 128)) {
+ SILC_LOG_ERROR(("Malformed username '%s'", client->username));
+ return FALSE;
+ }
+ if (!silc_identifier_verify(client->hostname, strlen(client->hostname),
+ SILC_STRING_UTF8, 256)) {
+ SILC_LOG_ERROR(("Malformed hostname '%s'", client->hostname));
+ return FALSE;
+ }
+ if (!silc_utf8_valid(client->realname, strlen(client->realname))) {
+ SILC_LOG_ERROR(("Malformed realname '%s'", client->realname));
+ return FALSE;
+ }
+
+ if (!client->internal->params->dont_register_crypto_library) {
+ /* 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->md5hash);
silc_schedule_one(client->schedule, 0);
}
-static void silc_client_entry_destructor(SilcIDCache cache,
- SilcIDCacheEntry entry)
-{
- silc_free(entry->name);
-}
-
/* Allocates and adds new connection to the client. This adds the allocated
connection to the connection table and returns a pointer to it. A client
can have multiple connections to multiple servers. Every connection must
conn->remote_port = port;
conn->context = context;
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);
+ silc_idcache_alloc(0, SILC_ID_CLIENT, NULL, FALSE, TRUE);
+ conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL,
+ FALSE, TRUE);
+ conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL,
+ FALSE, TRUE);
conn->internal->pending_commands = silc_dlist_init();
conn->internal->ftp_sessions = silc_dlist_init();
SilcClient client = (SilcClient)ctx->client;
client->internal->ops->connected(client, ctx->sock->user_data,
- SILC_CLIENT_CONN_ERROR);
+ SILC_CLIENT_CONN_ERROR_KE);
if (ctx->packet)
silc_packet_context_free(ctx->packet);
silc_free(ctx);
(SilcClientConnAuthInternalContext *)context;
SilcClient client = (SilcClient)ctx->client;
- client->internal->ops->connected(client, ctx->sock->user_data,
- SILC_CLIENT_CONN_ERROR);
+ client->internal->ops->connected(client, ctx->sock->user_data, ctx->status);
silc_free(ctx);
}
silc_free(ctx);
/* Notify application of failure */
- client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
+ client->internal->ops->connected(client, conn,
+ SILC_CLIENT_CONN_ERROR_TIMEOUT);
}
return;
}
protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
/* Error occured during protocol */
SILC_LOG_DEBUG(("Error during authentication protocol"));
+ ctx->status = SILC_CLIENT_CONN_ERROR_AUTH;
goto err;
}
unsigned char *old_id;
SilcUInt16 old_id_len;
- if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
+ if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len)) {
+ ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
goto err;
+ }
old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
if (!old_client_id) {
silc_free(old_id);
+ ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
goto err;
}
if (!auth) {
silc_free(old_client_id);
silc_free(old_id);
+ ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
goto err;
}
/* Parse the incoming packet type */
silc_client_packet_parse_type(client, sock, packet);
- silc_packet_context_free(packet);
- silc_free(parser_context);
/* Reprocess the buffer since we'll return FALSE. This is because
the `conn->internal->receive_key' might have become valid by processing
silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
silc_client_packet_parse, client);
+ silc_packet_context_free(packet);
+ silc_free(parser_context);
+
return FALSE;
}
case SILC_PACKET_PRIVATE_MESSAGE_KEY:
/*
- * Received private message key
+ * Received private message key indicator
*/
+ silc_client_private_message_key(client, sock, packet);
break;
case SILC_PACKET_COMMAND:
SilcSocketConnection sock)
{
if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
- (SILC_IS_DISCONNECTED(sock) == FALSE)) {
- silc_packet_send(sock, TRUE);
+ !(SILC_IS_DISCONNECTED(sock))) {
+ int ret;
+
+ ret = silc_packet_send(sock, TRUE);
+ if (ret == -2) {
+ if (sock->outbuf && sock->outbuf->len > 0) {
+ /* Couldn't send all data, put the queue back up, we'll send
+ rest later. */
+ SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
+ SILC_SET_OUTBUF_PENDING(sock);
+ return;
+ }
+ }
+
+ /* Purged all data */
SILC_UNSET_OUTBUF_PENDING(sock);
SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
silc_buffer_clear(sock->outbuf);
/* Notify application that connection is created to server */
client->internal->ops->connected(client, conn, success ?
SILC_CLIENT_CONN_SUCCESS_RESUME :
- SILC_CLIENT_CONN_ERROR);
+ SILC_CLIENT_CONN_ERROR_RESUME);
if (success) {
/* Issue INFO command to fetch the real server name and server
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;
NULL, NULL, NULL,
TRUE);
- /* Put it to the ID cache */
- silc_idcache_add(conn->internal->client_cache,
- strdup(conn->nickname), conn->local_id,
+ /* 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 (connecting) {
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))
+ 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);
SilcChannelUser chu;
silc_hash_table_list(client_entry->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+ 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);
SilcChannelUser chu;
silc_hash_table_list(old->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+ 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);
/* Notify application */
client->internal->ops->failure(client, sock->user_data, sock->protocol,
- (void *)failure);
+ SILC_32_TO_PTR(failure));
}
}