silcclient.h and cleaned up the structures a bit.
+Fri Nov 1 10:30:26 CET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Moved the SilcClient and SilcClientConnection from client.h
+ to the public lib/silcclient/silcclient.h. Changed the
+ structures a bit.
+
Thu Oct 31 22:44:07 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* If version string in silc_clinet_alloc is NULL the library
o Check whether we can fully comply with RFC 2779.
-
-TODO in SILC Protocol
-=====================
-
- o Inviting and banning by public key should be made possible. To be
- included in protocol version 1.2.
-
- o UTF-8 support/requirement for nicknames & channel names. UTF-8 support
- in terminals and OS's are so hazy that this matter is left for
- consideration in next version of the protocol (1.2). For good UTF-8
- reference and tutorial see: http://www.cl.cam.ac.uk/~mgk25/unicode.html.
- What should CLI application do if it receives nickname that it cannot
- display without messing up the terminal? If UTF-8 is mandatory in
- SILC then SILC clients cannot be allowed to start on terminals that do
- not support UTF-8 (which renders 98% of users unable to use CLI SILC
- app without hacking their environment). See also site
- http://gratrix.net/unicode/
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->params.detach_data = silc_memdup(params->detach_data,
- params->detach_data_len);
- conn->params.detach_data_len = params->detach_data_len;
+ 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++)
if (client->internal->conns[i] == conn) {
- 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);
+ silc_idcache_free(conn->internal->client_cache);
+ silc_idcache_free(conn->internal->channel_cache);
+ silc_idcache_free(conn->internal->server_cache);
+ if (conn->internal->pending_commands)
+ silc_dlist_uninit(conn->internal->pending_commands);
silc_free(conn->remote_host);
- if (conn->ftp_sessions)
- silc_dlist_uninit(conn->ftp_sessions);
+ if (conn->internal->ftp_sessions)
+ silc_dlist_uninit(conn->internal->ftp_sessions);
+ silc_free(conn->internal);
silc_free(conn);
client->internal->conns[i] = NULL;
goto err;
}
- if (conn->params.detach_data) {
+ if (conn->internal->params.detach_data) {
/* Send RESUME_CLIENT packet to the server, which is used to resume
old detached session back. */
SilcBuffer auth;
/* Generate authentication data that server will verify */
auth = silc_auth_public_key_auth_generate(client->public_key,
client->private_key,
- client->rng, conn->hash,
+ client->rng,
+ conn->internal->hash,
old_client_id, SILC_ID_CLIENT);
if (!auth) {
silc_free(old_client_id);
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);
/* 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,
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);
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,
/* 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;
}
if (hmac)
- sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
+ sequence = ((SilcClientConnection)sock->user_data)->internal->psn_send++;
}
block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
SilcClientCommandPending *r;
bool ret;
- if (silc_idcache_get_all(conn->client_cache, &list)) {
+ 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);
silc_idcache_list_free(list);
}
- if (silc_idcache_get_all(conn->channel_cache, &list)) {
+ 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);
silc_idcache_list_free(list);
}
- if (silc_idcache_get_all(conn->server_cache, &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);
}
/* Clear ID caches */
- if (conn->client_cache)
- silc_idcache_free(conn->client_cache);
- if (conn->channel_cache)
- silc_idcache_free(conn->channel_cache);
- if (conn->server_cache)
- silc_idcache_free(conn->server_cache);
+ 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);
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->rekey)
- silc_free(conn->rekey);
-
- if (conn->active_session) {
+ 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);
+ if (conn->internal->rekey)
+ silc_free(conn->internal->rekey);
+
+ if (conn->internal->active_session) {
sock->user_data = NULL;
- silc_client_ftp_session_free(conn->active_session);
- conn->active_session = NULL;
+ silc_client_ftp_session_free(conn->internal->active_session);
+ conn->internal->active_session = NULL;
}
silc_client_ftp_free_sessions(client, conn);
- silc_dlist_start(conn->pending_commands);
- while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END)
- silc_dlist_del(conn->pending_commands, r);
- if (conn->pending_commands)
- silc_dlist_uninit(conn->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);
+ if (conn->internal->pending_commands)
+ silc_dlist_uninit(conn->internal->pending_commands);
memset(conn, 0, sizeof(*conn));
silc_client_del_connection(client, conn);
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);
}
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) {
conn->cmd_ident, 1, 5, sidp->data, sidp->len);
silc_buffer_free(sidp);
- if (!conn->params.detach_data) {
+ 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))
{
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;
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. */
/* 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);
}
int ret;
/* If we haven't send our request then ignore this one. */
- if (!conn->connauth)
+ if (!conn->internal->connauth)
return;
/* Parse the payload */
/* 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
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
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);
#define CLIENT_H
/* Forward declarations */
+typedef struct SilcClientStruct *SilcClient;
+typedef struct SilcClientConnectionStruct *SilcClientConnection;
+typedef struct SilcClientPingStruct SilcClientPing;
+typedef struct SilcClientAwayStruct SilcClientAway;
+typedef struct SilcClientKeyAgreementStruct *SilcClientKeyAgreement;
+typedef struct SilcClientFtpSessionStruct *SilcClientFtpSession;
+typedef struct SilcClientEntryStruct *SilcClientEntry;
+typedef struct SilcChannelEntryStruct *SilcChannelEntry;
+typedef struct SilcServerEntryStruct *SilcServerEntry;
+typedef struct SilcClientCommandStruct *SilcClientCommand;
+typedef struct SilcClientCommandContextStruct *SilcClientCommandContext;
+typedef struct SilcClientCommandReplyContextStruct
+ *SilcClientCommandReplyContext;
+typedef struct SilcChannelUserStruct *SilcChannelUser;
typedef struct SilcClientInternalStruct *SilcClientInternal;
-
-/* Generic rekey context for connections */
-typedef struct {
- /* Current sending encryption key, provided for re-key. The `pfs'
- is TRUE if the Perfect Forward Secrecy is performed in re-key. */
- unsigned char *send_enc_key;
- SilcUInt32 enc_key_len;
- int ske_group;
- bool pfs;
- SilcUInt32 timeout;
- void *context;
-} *SilcClientRekey;
-
-/* Context to hold the connection authentication request callbacks that
- will be called when the server has replied back to our request about
- current authentication method in the session. */
-typedef struct {
- SilcConnectionAuthRequest callback;
- void *context;
- SilcTask timeout;
-} *SilcClientConnAuthRequest;
-
-/* Connection structure used in client to associate all the important
- connection specific data to this structure. */
-struct SilcClientConnectionStruct {
- /*
- * Local data
- */
- char *nickname;
-
- /* Local client ID for this connection */
- SilcClientID *local_id;
-
- /* Decoded local ID so that the above defined ID would not have
- to be decoded for every packet. */
- unsigned char *local_id_data;
- SilcUInt32 local_id_data_len;
-
- /* Own client entry. */
- SilcClientEntry local_entry;
-
- /*
- * Remote data
- */
- char *remote_host;
- int remote_port;
- int remote_type;
- char *remote_info;
-
- /* Remote server ID for this connection */
- SilcServerID *remote_id;
-
- /* Decoded remote ID so that the above defined ID would not have
- to be decoded for every packet. */
- unsigned char *remote_id_data;
- SilcUInt32 remote_id_data_len;
-
- /*
- * Common data
- */
- /* Keys and stuff negotiated in the SKE protocol */
- SilcCipher send_key;
- SilcCipher receive_key;
- SilcHmac hmac_send;
- SilcHmac hmac_receive;
- SilcHash hash;
- SilcUInt32 psn_send;
- SilcUInt32 psn_receive;
-
- /* Client ID and Channel ID cache. Messages transmitted in SILC network
- are done using different unique ID's. These are the cache for
- thoses ID's used in the communication. */
- SilcIDCache client_cache;
- SilcIDCache channel_cache;
- SilcIDCache server_cache;
-
- /* Current channel on window. All channels are saved (allocated) into
- the cache entries. */
- SilcChannelEntry current_channel;
-
- /* Socket connection object for this connection (window). This
- object will have a back-pointer to this window object for fast
- referencing (sock->user_data). */
- SilcSocketConnection sock;
-
- /* Pending command queue for this connection */
- SilcDList pending_commands;
-
- /* Current command identifier, 0 not used */
- SilcUInt16 cmd_ident;
-
- /* Requested pings. */
- SilcClientPing *ping;
- SilcUInt32 ping_count;
-
- /* Set away message */
- SilcClientAway *away;
-
- /* Re-key context */
- SilcClientRekey rekey;
-
- /* Authentication request context. */
- SilcClientConnAuthRequest connauth;
-
- /* File transmission sessions */
- SilcDList ftp_sessions;
- SilcUInt32 next_session_id;
- SilcClientFtpSession active_session;
-
- /* Requested Attributes */
- SilcHashTable attrs;
-
- /* Pointer back to the SilcClient. This object is passed to the application
- and the actual client object is accesible through this pointer. */
- SilcClient client;
-
- /* Connection parameters */
- SilcClientConnectionParams params;
-
- /* User data context. Library does not touch this. */
- void *context;
-};
-
-/* Main client structure. */
-struct SilcClientStruct {
- char *username; /* Username, must be set by application */
- char *nickname; /* Nickname, may be set by application */
- char *hostname; /* hostname, must be set by application */
- char *realname; /* Real name, must be set be application */
-
- SilcPublicKey public_key; /* Public key of user, set by application */
- SilcPrivateKey private_key; /* Private key of user, set by application */
- SilcPKCS pkcs; /* PKCS allocated by application */
-
- SilcSchedule schedule; /* Scheduler, automatically allocated by
- the client library. */
-
- /* Random Number Generator. Application should use this as its primary
- random number generator. */
- SilcRng rng;
-
- /* Application specific user data pointer. Client library does not
- touch this. This the context sent as argument to silc_client_alloc. */
- void *application;
-
- /* Generic hash context for application usage */
- SilcHash md5hash;
- SilcHash sha1hash;
-
- /* Internal data for client library. Application cannot access this
- data at all. */
- SilcClientInternal internal;
-};
-
+typedef struct SilcClientConnectionInternalStruct
+ *SilcClientConnectionInternal;
+
#endif
/* If nothing is set by application assume that we don't want to use
attributes, ignore the request. */
- if (!conn->attrs)
+ if (!conn->internal->attrs)
return NULL;
/* Always put our public key. */
if (attribute == SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE)
continue;
- silc_hash_table_find_foreach(conn->attrs, (void *)(SilcUInt32)attribute,
+ silc_hash_table_find_foreach(conn->internal->attrs,
+ (void *)(SilcUInt32)attribute,
silc_client_attributes_process_foreach,
&f);
}
if (!attr)
return NULL;
- if (!conn->attrs)
- conn->attrs = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
- NULL, silc_client_attribute_destruct,
- NULL, TRUE);
- silc_hash_table_add(conn->attrs, (void *)(SilcUInt32)attribute, attr);
+ if (!conn->internal->attrs)
+ conn->internal->attrs =
+ silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL,
+ NULL, silc_client_attribute_destruct,
+ NULL, TRUE);
+ silc_hash_table_add(conn->internal->attrs,
+ (void *)(SilcUInt32)attribute, attr);
return attr;
}
if (!attr)
return;
attribute = silc_attribute_get_attribute(attr);
- silc_hash_table_del_by_context(conn->attrs,
+ silc_hash_table_del_by_context(conn->internal->attrs,
(void *)(SilcUInt32)attribute, attr);
}
{
bool ret;
- if (!conn->attrs)
+ if (!conn->internal->attrs)
return FALSE;
if (attr) {
attribute = silc_attribute_get_attribute(attr);
- ret = silc_hash_table_del_by_context(conn->attrs,
+ ret = silc_hash_table_del_by_context(conn->internal->attrs,
(void *)(SilcUInt32)attribute, attr);
} else if (attribute) {
- silc_hash_table_find_foreach(conn->attrs, (void *)(SilcUInt32)attribute,
+ silc_hash_table_find_foreach(conn->internal->attrs,
+ (void *)(SilcUInt32)attribute,
silc_client_attribute_del_foreach, conn);
ret = TRUE;
} else{
}
if (ret)
- if (!silc_hash_table_count(conn->attrs)) {
- silc_hash_table_free(conn->attrs);
- conn->attrs = NULL;
+ if (!silc_hash_table_count(conn->internal->attrs)) {
+ silc_hash_table_free(conn->internal->attrs);
+ conn->internal->attrs = NULL;
}
return ret;
const SilcHashTable silc_client_attributes_get(SilcClient client,
SilcClientConnection conn)
{
- return (const SilcHashTable)conn->attrs;
+ return (const SilcHashTable)conn->internal->attrs;
}
/* Construct a Requested Attributes buffer. If the `attribute' is zero (0)
client->rng);
/* Get data used in packet header encryption, keys and stuff. */
- cipher = conn->send_key;
- hmac = conn->hmac_send;
+ cipher = conn->internal->send_key;
+ hmac = conn->internal->hmac_send;
id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
/* Set the packet context pointers. The destination ID is always
/* Encrypt the header and padding of the packet. This is encrypted
with normal session key shared with our server. */
- silc_packet_encrypt(cipher, hmac, conn->psn_send++,
+ silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
(SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len +
packetdata.padlen);
}
/* Set this as active session */
- conn->active_session = session;
+ conn->internal->active_session = session;
out:
silc_ske_free_key_material(ctx->keymat);
void silc_client_ftp_free_sessions(SilcClient client,
SilcClientConnection conn)
{
- if (conn->ftp_sessions) {
+ if (conn->internal->ftp_sessions) {
SilcClientFtpSession session;
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->sock)
session->sock->user_data = NULL;
silc_client_ftp_session_free(session);
}
- silc_dlist_del(conn->ftp_sessions, session);
+ silc_dlist_del(conn->internal->ftp_sessions, session);
}
}
{
SilcClientFtpSession session;
- if (!conn->ftp_sessions)
+ if (!conn->internal->ftp_sessions)
return;
/* Get the session */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->client_entry == client_entry) {
if (session->sock)
session->sock->user_data = NULL;
SILC_LOG_DEBUG(("Free session"));
- if (session->conn && session->conn->ftp_sessions)
- silc_dlist_del(session->conn->ftp_sessions, session);
+ if (session->conn && session->conn->internal->ftp_sessions)
+ silc_dlist_del(session->conn->internal->ftp_sessions, session);
- if (session->conn && session->conn->active_session == session)
- session->conn->active_session = NULL;
+ if (session->conn && session->conn->internal->active_session == session)
+ session->conn->internal->active_session = NULL;
if (session->sftp) {
if (session->server)
if (session->sock->user_data) {
conn = (SilcClientConnection)session->sock->user_data;
- if (conn->active_session == session)
- conn->active_session = NULL;
+ if (conn->internal->active_session == session)
+ conn->internal->active_session = NULL;
silc_client_close_connection_real(session->client, session->sock, conn);
} else {
SILC_LOG_DEBUG(("Start"));
/* Check for existing session for `filepath'. */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->filepath && !strcmp(session->filepath, filepath) &&
session->client_entry == client_entry)
return SILC_CLIENT_FILE_ALREADY_STARTED;
/* Add new session */
session = silc_calloc(1, sizeof(*session));
- session->session_id = ++conn->next_session_id;
+ session->session_id = ++conn->internal->next_session_id;
session->client = client;
session->conn = conn;
session->client_entry = client_entry;
session->monitor_context = monitor_context;
session->filepath = strdup(filepath);
session->server = TRUE;
- silc_dlist_add(conn->ftp_sessions, session);
+ silc_dlist_add(conn->internal->ftp_sessions, session);
path = silc_calloc(strlen(filepath) + 9, sizeof(*path));
silc_strncat(path, strlen(filepath) + 9, "file://", 7);
SILC_LOG_DEBUG(("Start, Session ID: %d", session_id));
/* Get the session */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->session_id == session_id) {
break;
}
SILC_LOG_DEBUG(("Start, Session ID: %d", session_id));
/* Get the session */
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->session_id == session_id) {
break;
}
client_entry = clients[0];
- silc_dlist_start(conn->ftp_sessions);
- while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->ftp_sessions);
+ while ((session = silc_dlist_get(conn->internal->ftp_sessions))
+ != SILC_LIST_END) {
if (session->client_entry == client_entry && !session->server)
break;
}
/* Add new session */
session = silc_calloc(1, sizeof(*session));
- session->session_id = ++conn->next_session_id;
+ session->session_id = ++conn->internal->next_session_id;
session->client = client;
session->conn = conn;
session->client_entry = client_entry;
- silc_dlist_add(conn->ftp_sessions, session);
+ silc_dlist_add(conn->internal->ftp_sessions, session);
/* Let the application know */
client->internal->ops->ftp(client, conn, client_entry,
/* If we have active FTP session then give the packet directly to the
protocol processor. */
- if (conn->active_session) {
+ if (conn->internal->active_session) {
/* Give it to the SFTP */
- if (conn->active_session->server)
- silc_sftp_server_receive_process(conn->active_session->sftp, sock,
- packet);
+ if (conn->internal->active_session->server)
+ silc_sftp_server_receive_process(conn->internal->active_session->sftp,
+ sock, packet);
else
- silc_sftp_client_receive_process(conn->active_session->sftp, sock,
- packet);
+ silc_sftp_client_receive_process(conn->internal->active_session->sftp,
+ sock, packet);
} else {
/* We don't have active session, resolve the remote client information
and then try to find the correct session. */
#ifndef CLIENT_INTERNAL_H
#define CLIENT_INTERNAL_H
+/* Context to hold the connection authentication request callbacks that
+ will be called when the server has replied back to our request about
+ current authentication method in the session. */
+typedef struct {
+ SilcConnectionAuthRequest callback;
+ void *context;
+ SilcTask timeout;
+} *SilcClientConnAuthRequest;
+
+/* Generic rekey context for connections */
+typedef struct {
+ /* Current sending encryption key, provided for re-key. The `pfs'
+ is TRUE if the Perfect Forward Secrecy is performed in re-key. */
+ unsigned char *send_enc_key;
+ SilcUInt32 enc_key_len;
+ int ske_group;
+ bool pfs;
+ SilcUInt32 timeout;
+ void *context;
+} *SilcClientRekey;
+
/* Internal context for connection process. This is needed as we
doing asynchronous connecting. */
typedef struct {
char *silc_client_version;
};
+/* Internal context for conn->internal in SilcClientConnection. */
+struct SilcClientConnectionInternalStruct {
+ /* Keys and stuff negotiated in the SKE protocol */
+ SilcCipher send_key;
+ SilcCipher receive_key;
+ SilcHmac hmac_send;
+ SilcHmac hmac_receive;
+ SilcHash hash;
+ SilcUInt32 psn_send;
+ SilcUInt32 psn_receive;
+
+ /* Client ID and Channel ID cache. Messages transmitted in SILC network
+ are done using different unique ID's. These are the cache for
+ thoses ID's used in the communication. */
+ SilcIDCache client_cache;
+ SilcIDCache channel_cache;
+ SilcIDCache server_cache;
+
+ /* Pending command queue for this connection */
+ SilcDList pending_commands;
+
+ /* Requested pings. */
+ SilcClientPing *ping;
+ SilcUInt32 ping_count;
+
+ /* Set away message */
+ SilcClientAway *away;
+
+ /* Re-key context */
+ SilcClientRekey rekey;
+
+ /* Authentication request context. */
+ SilcClientConnAuthRequest connauth;
+
+ /* File transmission sessions */
+ SilcDList ftp_sessions;
+ SilcUInt32 next_session_id;
+ SilcClientFtpSession active_session;
+
+ /* Requested Attributes */
+ SilcHashTable attrs;
+
+ /* Connection parameters */
+ SilcClientConnectionParams params;
+};
+
/* Session resuming callback */
typedef void (*SilcClientResumeSessionCallback)(SilcClient client,
SilcClientConnection conn,
silc_client_remove_from_channels(client, conn, client_entry);
/* Remove from cache */
- silc_idcache_del_by_context(conn->client_cache, client_entry);
+ silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
/* Get signoff message */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (tmp_nick && !strcmp(tmp, tmp_nick)) {
/* Nickname didn't change. Update only the ID */
- silc_idcache_del_by_context(conn->client_cache, client_entry);
+ silc_idcache_del_by_context(conn->internal->client_cache,
+ client_entry);
silc_free(client_entry->id);
client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
- silc_idcache_add(conn->client_cache, strdup(tmp),
+ silc_idcache_add(conn->internal->client_cache, strdup(tmp),
client_entry->id, client_entry, 0, NULL);
/* Notify application */
}
/* Remove the old from cache */
- silc_idcache_del_by_context(conn->client_cache, client_entry);
+ silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
/* Replace old ID entry with new one on all channels. */
silc_client_replace_from_channels(client, conn, client_entry,
/* We have private message specific key */
/* Get data used in the encryption */
- cipher = conn->send_key;
- hmac = conn->hmac_send;
+ cipher = conn->internal->send_key;
+ hmac = conn->internal->hmac_send;
block_len = silc_cipher_get_block_len(cipher);
/* Set the packet context pointers. */
}
/* Encrypt the header and padding of the packet. */
- silc_packet_encrypt(cipher, hmac, conn->psn_send++,
+ silc_packet_encrypt(cipher, hmac, conn->internal->psn_send++,
(SilcBuffer)&packet, SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len +
packetdata.padlen);
/* See if we are away (gone). If we are away we will reply to the
sender with the set away message. */
- if (conn->away && conn->away->away && !(flags & SILC_MESSAGE_FLAG_NOREPLY)) {
+ if (conn->internal->away && conn->internal->away->away &&
+ !(flags & SILC_MESSAGE_FLAG_NOREPLY)) {
/* If it's me, ignore */
if (SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
goto out;
silc_client_send_private_message(client, conn, remote_client,
SILC_MESSAGE_FLAG_AUTOREPLY |
SILC_MESSAGE_FLAG_NOREPLY,
- conn->away->away,
- strlen(conn->away->away), TRUE);
+ conn->internal->away->away,
+ strlen(conn->internal->away->away), TRUE);
}
out:
SilcIDCacheList list;
SilcClientEntry entry;
- if (!silc_idcache_get_all(conn->client_cache, &list))
+ if (!silc_idcache_get_all(conn->internal->client_cache, &list))
return NULL;
if (!silc_idcache_list_count(list)) {
SilcClientConnection conn,
char *message)
{
- if (!message && conn->away) {
- silc_free(conn->away->away);
- silc_free(conn->away);
- conn->away = NULL;
+ if (!message && conn->internal->away) {
+ silc_free(conn->internal->away->away);
+ silc_free(conn->internal->away);
+ conn->internal->away = NULL;
}
if (message) {
- if (!conn->away)
- conn->away = silc_calloc(1, sizeof(*conn->away));
- if (conn->away->away)
- silc_free(conn->away->away);
- conn->away->away = strdup(message);
+ if (!conn->internal->away)
+ conn->internal->away = silc_calloc(1, sizeof(*conn->internal->away));
+ if (conn->internal->away->away)
+ silc_free(conn->internal->away->away);
+ conn->internal->away->away = strdup(message);
}
}
SILC_LOG_DEBUG(("Start"));
silc_free(conn->nickname);
- silc_buffer_set(&detach, conn->params.detach_data,
- conn->params.detach_data_len);
+ silc_buffer_set(&detach, conn->internal->params.detach_data,
+ conn->internal->params.detach_data_len);
SILC_LOG_HEXDUMP(("Detach data"), detach.data, detach.len);
/* Second, send IDENTIFY command of all channels we know about. These
are the channels we've joined to according our detachment data. */
- if (silc_idcache_get_all(conn->channel_cache, &list)) {
+ if (silc_idcache_get_all(conn->internal->channel_cache, &list)) {
unsigned char **res_argv = NULL;
SilcUInt32 *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0;
reply->ident = ident;
reply->context = context;
reply->callback = callback;
- silc_dlist_add(conn->pending_commands, reply);
+ silc_dlist_add(conn->internal->pending_commands, reply);
}
/* Deletes pending command by reply command type. */
{
SilcClientCommandPending *r;
- if (!conn->pending_commands)
+ if (!conn->internal->pending_commands)
return;
- silc_dlist_start(conn->pending_commands);
- while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->pending_commands);
+ while ((r = silc_dlist_get(conn->internal->pending_commands))
+ != SILC_LIST_END) {
if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
r->reply_check))
&& r->ident == ident) {
- silc_dlist_del(conn->pending_commands, r);
+ silc_dlist_del(conn->internal->pending_commands, r);
silc_free(r);
}
}
SilcClientCommandPendingCallbacks callbacks = NULL;
int i = 0;
- silc_dlist_start(conn->pending_commands);
- while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END) {
+ silc_dlist_start(conn->internal->pending_commands);
+ while ((r = silc_dlist_get(conn->internal->pending_commands))
+ != SILC_LIST_END) {
if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
&& r->ident == ident) {
callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
name = cmd->argv[1];
/* Get the Channel ID of the channel */
- if (silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
+ if (silc_idcache_find_by_name_one(conn->internal->channel_cache,
+ name, &id_cache)) {
channel = (SilcChannelEntry)id_cache->context;
idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
}
}
/* Get the Channel ID of the channel */
- if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
+ if (!silc_idcache_find_by_name_one(conn->internal->channel_cache,
+ name, &id_cache)) {
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
goto out;
}
}
/* Start counting time */
- for (i = 0; i < conn->ping_count; i++) {
- if (conn->ping[i].dest_id == NULL) {
- conn->ping[i].start_time = time(NULL);
- conn->ping[i].dest_id = id;
- conn->ping[i].dest_name = strdup(conn->remote_host);
+ for (i = 0; i < conn->internal->ping_count; i++) {
+ if (conn->internal->ping[i].dest_id == NULL) {
+ conn->internal->ping[i].start_time = time(NULL);
+ conn->internal->ping[i].dest_id = id;
+ conn->internal->ping[i].dest_name = strdup(conn->remote_host);
break;
}
}
- if (i >= conn->ping_count) {
- i = conn->ping_count;
- conn->ping = silc_realloc(conn->ping, sizeof(*conn->ping) * (i + 1));
- conn->ping[i].start_time = time(NULL);
- conn->ping[i].dest_id = id;
- conn->ping[i].dest_name = strdup(conn->remote_host);
- conn->ping_count++;
+ if (i >= conn->internal->ping_count) {
+ i = conn->internal->ping_count;
+ conn->internal->ping =
+ silc_realloc(conn->internal->ping,
+ sizeof(*conn->internal->ping) * (i + 1));
+ conn->internal->ping[i].start_time = time(NULL);
+ conn->internal->ping[i].dest_id = id;
+ conn->internal->ping[i].dest_name = strdup(conn->remote_host);
+ conn->internal->ping_count++;
}
/* Notify application */
}
/* Get the Channel ID of the channel */
- if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
+ if (!silc_idcache_find_by_name_one(conn->internal->channel_cache,
+ name, &id_cache)) {
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
goto out;
}
/* Encode the public key authentication payload */
auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
cmd->client->private_key,
- cmd->client->rng, conn->hash,
+ cmd->client->rng,
+ conn->internal->hash,
conn->local_id,
SILC_ID_CLIENT);
} else {
/* Encode the public key authentication payload */
auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
cmd->client->private_key,
- cmd->client->rng, conn->hash,
+ cmd->client->rng,
+ conn->internal->hash,
conn->local_id,
SILC_ID_CLIENT);
} else {
/* Take the new nickname too */
tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
if (tmp) {
- silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
+ silc_idcache_del_by_context(conn->internal->client_cache,
+ conn->local_entry);
if (conn->nickname)
silc_free(conn->nickname);
conn->nickname = strdup(tmp);
conn->local_entry->nickname = conn->nickname;
silc_client_nickname_format(cmd->client, conn, conn->local_entry);
- silc_idcache_add(conn->client_cache, strdup(tmp),
+ silc_idcache_add(conn->internal->client_cache, strdup(tmp),
conn->local_entry->id, conn->local_entry, 0, NULL);
}
curtime = time(NULL);
id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_len,
cmd->packet->src_id_type);
- if (!id || !conn->ping) {
+ if (!id || !conn->internal->ping) {
COMMAND_REPLY_ERROR;
goto out;
}
- for (i = 0; i < conn->ping_count; i++) {
- if (!conn->ping[i].dest_id)
+ for (i = 0; i < conn->internal->ping_count; i++) {
+ if (!conn->internal->ping[i].dest_id)
continue;
- if (SILC_ID_SERVER_COMPARE(conn->ping[i].dest_id, id)) {
- diff = curtime - conn->ping[i].start_time;
+ if (SILC_ID_SERVER_COMPARE(conn->internal->ping[i].dest_id, id)) {
+ diff = curtime - conn->internal->ping[i].start_time;
SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Ping reply from %s: %d second%s",
- conn->ping[i].dest_name, diff,
+ conn->internal->ping[i].dest_name, diff,
diff == 1 ? "" : "s");
- conn->ping[i].start_time = 0;
- silc_free(conn->ping[i].dest_id);
- conn->ping[i].dest_id = NULL;
- silc_free(conn->ping[i].dest_name);
- conn->ping[i].dest_name = NULL;
+ conn->internal->ping[i].start_time = 0;
+ silc_free(conn->internal->ping[i].dest_id);
+ conn->internal->ping[i].dest_id = NULL;
+ silc_free(conn->internal->ping[i].dest_name);
+ conn->internal->ping[i].dest_name = NULL;
break;
}
}
bool found = FALSE;
/* Find ID from cache */
- if (!silc_idcache_find_by_name(conn->client_cache, (char *)nickname, &list))
+ if (!silc_idcache_find_by_name(conn->internal->client_cache,
+ (char *)nickname, &list))
return NULL;
if (!silc_idcache_list_count(list)) {
SILC_LOG_DEBUG(("Start"));
/* Find ID from cache */
- if (!silc_idcache_find_by_name(conn->client_cache, (char *)nickname,
- &list)) {
+ if (!silc_idcache_find_by_name(conn->internal->client_cache,
+ (char *)nickname, &list)) {
identify:
if (query) {
}
/* Get the client entry */
- if (silc_idcache_find_by_id_one_ext(i->conn->client_cache,
+ if (silc_idcache_find_by_id_one_ext(i->conn->internal->client_cache,
(void *)client_id,
NULL, NULL,
silc_hash_client_id_compare, NULL,
/* Check if we have this client cached already. */
ret =
- silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
- NULL, NULL,
+ silc_idcache_find_by_id_one_ext(conn->internal->client_cache,
+ (void *)client_id, NULL, NULL,
silc_hash_client_id_compare, NULL,
&id_cache);
silc_id_render(client_id, SILC_ID_CLIENT)));
/* Find ID from cache */
- if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
- NULL, NULL,
+ if (!silc_idcache_find_by_id_one_ext(conn->internal->client_cache,
+ (void *)client_id, NULL, NULL,
silc_hash_client_id_compare, NULL,
&id_cache))
return NULL;
silc_client_nickname_format(client, conn, client_entry);
/* Add client to cache, the non-formatted nickname is saved to cache */
- if (!silc_idcache_add(conn->client_cache, nick, client_entry->id,
+ if (!silc_idcache_add(conn->internal->client_cache, nick, client_entry->id,
(void *)client_entry, 0, NULL)) {
silc_free(client_entry->nickname);
silc_free(client_entry->username);
if (nick) {
/* Remove the old cache entry and create a new one */
- silc_idcache_del_by_context(conn->client_cache, client_entry);
- silc_idcache_add(conn->client_cache, nick, client_entry->id,
+ silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
+ silc_idcache_add(conn->internal->client_cache, nick, client_entry->id,
client_entry, 0, NULL);
}
}
bool silc_client_del_client(SilcClient client, SilcClientConnection conn,
SilcClientEntry client_entry)
{
- bool ret = silc_idcache_del_by_context(conn->client_cache, client_entry);
+ bool ret = silc_idcache_del_by_context(conn->internal->client_cache,
+ client_entry);
/* Remove from channels */
silc_client_remove_from_channels(client, conn, client_entry);
NULL, NULL, NULL, TRUE);
/* Put it to the ID cache */
- if (!silc_idcache_add(conn->channel_cache, channel->channel_name,
+ if (!silc_idcache_add(conn->internal->channel_cache, channel->channel_name,
(void *)channel->id, (void *)channel, 0, NULL)) {
silc_free(channel->channel_name);
silc_hash_table_free(channel->user_list);
bool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
SilcChannelEntry channel)
{
- bool ret = silc_idcache_del_by_context(conn->channel_cache, channel);
+ bool ret = silc_idcache_del_by_context(conn->internal->channel_cache,
+ channel);
SILC_LOG_DEBUG(("Start"));
SILC_LOG_DEBUG(("New Channel ID id(%s)",
silc_id_render(new_id, SILC_ID_CHANNEL)));
- silc_idcache_del_by_id(conn->channel_cache, channel->id);
+ silc_idcache_del_by_id(conn->internal->channel_cache, channel->id);
silc_free(channel->id);
channel->id = new_id;
- return silc_idcache_add(conn->channel_cache, channel->channel_name,
+ return silc_idcache_add(conn->internal->channel_cache,
+ channel->channel_name,
(void *)channel->id, (void *)channel, 0, NULL);
}
SILC_LOG_DEBUG(("Start"));
- if (!silc_idcache_find_by_name_one(conn->channel_cache, channel,
+ if (!silc_idcache_find_by_name_one(conn->internal->channel_cache, channel,
&id_cache))
return NULL;
SILC_LOG_DEBUG(("Start"));
- if (!silc_idcache_find_by_id_one(conn->channel_cache, channel_id,
+ if (!silc_idcache_find_by_id_one(conn->internal->channel_cache, channel_id,
&id_cache))
return NULL;
SILC_LOG_DEBUG(("Start"));
- if (!silc_idcache_find_by_name_one(conn->server_cache, server_name,
- &id_cache))
+ if (!silc_idcache_find_by_name_one(conn->internal->server_cache,
+ server_name, &id_cache))
return NULL;
entry = (SilcServerEntry)id_cache->context;
SILC_LOG_DEBUG(("Start"));
- if (!silc_idcache_find_by_id_one(conn->server_cache, (void *)server_id,
- &id_cache))
+ if (!silc_idcache_find_by_id_one(conn->internal->server_cache,
+ (void *)server_id, &id_cache))
return NULL;
entry = (SilcServerEntry)id_cache->context;
server_entry->server_info = strdup(server_info);
/* Add server to cache */
- if (!silc_idcache_add(conn->server_cache, server_entry->server_name,
+ if (!silc_idcache_add(conn->internal->server_cache,
+ server_entry->server_name,
server_entry->server_id, server_entry, 0, NULL)) {
silc_free(server_entry->server_id);
silc_free(server_entry->server_name);
bool silc_client_del_server(SilcClient client, SilcClientConnection conn,
SilcServerEntry server)
{
- bool ret = silc_idcache_del_by_context(conn->server_cache, server);
+ bool ret = silc_idcache_del_by_context(conn->internal->server_cache, server);
silc_free(server->server_name);
silc_free(server->server_info);
silc_free(server->server_id);
if (server_name && (!server_entry->server_name ||
strcmp(server_entry->server_name, server_name))) {
- silc_idcache_del_by_context(conn->server_cache, server_entry);
+ silc_idcache_del_by_context(conn->internal->server_cache, server_entry);
silc_free(server_entry->server_name);
server_entry->server_name = strdup(server_name);
- silc_idcache_add(conn->server_cache, server_entry->server_name,
+ silc_idcache_add(conn->internal->server_cache, server_entry->server_name,
server_entry->server_id,
server_entry, 0, NULL);
}
SILC_LOG_DEBUG(("Setting new keys into use"));
/* Allocate cipher to be used in the communication */
- silc_cipher_alloc((char *)cname, &conn->send_key);
- silc_cipher_alloc((char *)cname, &conn->receive_key);
- silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_send);
- silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL, &conn->hmac_receive);
+ silc_cipher_alloc((char *)cname, &conn->internal->send_key);
+ silc_cipher_alloc((char *)cname, &conn->internal->receive_key);
+ silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL,
+ &conn->internal->hmac_send);
+ silc_hmac_alloc((char *)silc_hmac_get_name(hmac), NULL,
+ &conn->internal->hmac_receive);
if (is_responder == TRUE) {
- silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->receive_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
- silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
+ silc_cipher_set_iv(conn->internal->send_key, keymat->receive_iv);
+ silc_cipher_set_key(conn->internal->receive_key, keymat->send_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
- silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
+ silc_cipher_set_iv(conn->internal->receive_key, keymat->send_iv);
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->receive_hmac_key,
keymat->hmac_key_len);
- silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_receive, keymat->send_hmac_key,
keymat->hmac_key_len);
} else {
- silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->send_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->send_key, keymat->send_iv);
- silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
+ silc_cipher_set_iv(conn->internal->send_key, keymat->send_iv);
+ silc_cipher_set_key(conn->internal->receive_key, keymat->receive_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
- silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
+ silc_cipher_set_iv(conn->internal->receive_key, keymat->receive_iv);
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->send_hmac_key,
keymat->hmac_key_len);
- silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
+ silc_hmac_set_key(conn->internal->hmac_receive, keymat->receive_hmac_key,
keymat->hmac_key_len);
}
/* Rekey stuff */
- conn->rekey = silc_calloc(1, sizeof(*conn->rekey));
- conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
- keymat->enc_key_len / 8);
- conn->rekey->enc_key_len = keymat->enc_key_len / 8;
+ conn->internal->rekey = silc_calloc(1, sizeof(*conn->internal->rekey));
+ conn->internal->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
+ keymat->enc_key_len / 8);
+ conn->internal->rekey->enc_key_len = keymat->enc_key_len / 8;
if (ske->start_payload->flags & SILC_SKE_SP_FLAG_PFS)
- conn->rekey->pfs = TRUE;
- conn->rekey->ske_group = silc_ske_group_get_number(group);
+ conn->internal->rekey->pfs = TRUE;
+ conn->internal->rekey->ske_group = silc_ske_group_get_number(group);
/* Save the HASH function */
- silc_hash_alloc(silc_hash_get_name(hash), &conn->hash);
+ silc_hash_alloc(silc_hash_get_name(hash), &conn->internal->hash);
}
/* Checks the version string of the server. */
if (ctx->responder == TRUE) {
if (send) {
- silc_cipher_set_key(conn->send_key, keymat->receive_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->receive_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->send_key, keymat->receive_iv);
- silc_hmac_set_key(conn->hmac_send, keymat->receive_hmac_key,
+ silc_cipher_set_iv(conn->internal->send_key, keymat->receive_iv);
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->receive_hmac_key,
keymat->hmac_key_len);
} else {
- silc_cipher_set_key(conn->receive_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->receive_key, keymat->send_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->receive_key, keymat->send_iv);
- silc_hmac_set_key(conn->hmac_receive, keymat->send_hmac_key,
+ silc_cipher_set_iv(conn->internal->receive_key, keymat->send_iv);
+ silc_hmac_set_key(conn->internal->hmac_receive, keymat->send_hmac_key,
keymat->hmac_key_len);
}
} else {
if (send) {
- silc_cipher_set_key(conn->send_key, keymat->send_enc_key,
+ silc_cipher_set_key(conn->internal->send_key, keymat->send_enc_key,
keymat->enc_key_len);
- silc_cipher_set_iv(conn->send_key, keymat->send_iv);
- silc_hmac_set_key(conn->hmac_send, keymat->send_hmac_key,
+ silc_cipher_set_iv(conn->internal->send_key, keymat->send_iv);
+ silc_hmac_set_key(conn->internal->hmac_send, keymat->send_hmac_key,
keymat->hmac_key_len);
} else {
- silc_cipher_set_key(conn->receive_key, keymat->receive_enc_key,
- keymat->enc_key_len);
- silc_cipher_set_iv(conn->receive_key, keymat->receive_iv);
- silc_hmac_set_key(conn->hmac_receive, keymat->receive_hmac_key,
- keymat->hmac_key_len);
+ silc_cipher_set_key(conn->internal->receive_key,
+ keymat->receive_enc_key, keymat->enc_key_len);
+ silc_cipher_set_iv(conn->internal->receive_key, keymat->receive_iv);
+ silc_hmac_set_key(conn->internal->hmac_receive,
+ keymat->receive_hmac_key, keymat->hmac_key_len);
}
}
/* Save the current sending encryption key */
if (!send) {
- memset(conn->rekey->send_enc_key, 0, conn->rekey->enc_key_len);
- silc_free(conn->rekey->send_enc_key);
- conn->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
- keymat->enc_key_len / 8);
- conn->rekey->enc_key_len = keymat->enc_key_len / 8;
+ memset(conn->internal->rekey->send_enc_key, 0,
+ conn->internal->rekey->enc_key_len);
+ silc_free(conn->internal->rekey->send_enc_key);
+ conn->internal->rekey->send_enc_key = silc_memdup(keymat->send_enc_key,
+ keymat->enc_key_len / 8);
+ conn->internal->rekey->enc_key_len = keymat->enc_key_len / 8;
}
}
{
SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
SilcSKEKeyMaterial *keymat;
- SilcUInt32 key_len = silc_cipher_get_key_len(conn->send_key);
- SilcUInt32 hash_len = silc_hash_len(conn->hash);
+ SilcUInt32 key_len = silc_cipher_get_key_len(conn->internal->send_key);
+ SilcUInt32 hash_len = silc_hash_len(conn->internal->hash);
SILC_LOG_DEBUG(("Generating new %s session keys (no PFS)",
send ? "sending" : "receiving"));
/* Generate the new key */
keymat = silc_calloc(1, sizeof(*keymat));
- silc_ske_process_key_material_data(conn->rekey->send_enc_key,
- conn->rekey->enc_key_len,
+ silc_ske_process_key_material_data(conn->internal->rekey->send_enc_key,
+ conn->internal->rekey->enc_key_len,
16, key_len, hash_len,
- conn->hash, keymat);
+ conn->internal->hash, keymat);
/* Set the keys into use */
silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
{
SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
SilcSKEKeyMaterial *keymat;
- SilcUInt32 key_len = silc_cipher_get_key_len(conn->send_key);
- SilcUInt32 hash_len = silc_hash_len(conn->hash);
+ SilcUInt32 key_len = silc_cipher_get_key_len(conn->internal->send_key);
+ SilcUInt32 hash_len = silc_hash_len(conn->internal->hash);
unsigned char *tmpbuf;
SilcUInt32 klen;
/* Generate the new key */
keymat = silc_calloc(1, sizeof(*keymat));
silc_ske_process_key_material_data(tmpbuf, klen, 16, key_len, hash_len,
- conn->hash, keymat);
+ conn->internal->hash, keymat);
/* Set the keys into use */
silc_client_protocol_rekey_validate(client, ctx, ctx->sock, keymat, send);
ctx->ske = silc_ske_alloc(client->rng, client);
ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
- silc_ske_group_get_by_number(conn->rekey->ske_group,
+ silc_ske_group_get_by_number(conn->internal->rekey->ske_group,
&ctx->ske->prop->group);
silc_ske_set_callbacks(ctx->ske,
*/
ctx->ske = silc_ske_alloc(client->rng, client);
ctx->ske->prop = silc_calloc(1, sizeof(*ctx->ske->prop));
- silc_ske_group_get_by_number(conn->rekey->ske_group,
+ silc_ske_group_get_by_number(conn->internal->rekey->ske_group,
&ctx->ske->prop->group);
silc_ske_set_callbacks(ctx->ske,
extern "C" {
#endif
-/* Forward declarations */
-typedef struct SilcClientStruct *SilcClient;
-typedef struct SilcClientConnectionStruct *SilcClientConnection;
-typedef struct SilcClientPingStruct SilcClientPing;
-typedef struct SilcClientAwayStruct SilcClientAway;
-typedef struct SilcClientKeyAgreementStruct *SilcClientKeyAgreement;
-typedef struct SilcClientFtpSessionStruct *SilcClientFtpSession;
-typedef struct SilcClientEntryStruct *SilcClientEntry;
-typedef struct SilcChannelEntryStruct *SilcChannelEntry;
-typedef struct SilcServerEntryStruct *SilcServerEntry;
-typedef struct SilcClientCommandStruct *SilcClientCommand;
-typedef struct SilcClientCommandContextStruct *SilcClientCommandContext;
-typedef struct SilcClientCommandReplyContextStruct
- *SilcClientCommandReplyContext;
-typedef struct SilcChannelUserStruct *SilcChannelUser;
+#include "client.h"
/* General definitions */
+/****s* silcclient/SilcClientAPI/SilcClient
+ *
+ * NAME
+ *
+ * typedef struct SilcClientStruct { ... } *SilcClient
+ *
+ * DESCRIPTION
+ *
+ * This is the actual SILC Client structure which represents one
+ * SILC Client. It is allocated with the silc_client_alloc function
+ * and given as argument to all SILC Client Library functions. It
+ * is initialized with silc_client_init function, and freed with
+ * silc_client_free function.
+ *
+ * SOURCE
+ */
+struct SilcClientStruct {
+ /*
+ * The following fields are set by application
+ */
+ char *nickname; /* Nickname, MAY be set by application */
+ char *username; /* Username, MUST be set by application */
+ char *hostname; /* hostname, MUST be set by application */
+ char *realname; /* Real name, MUST be set be application */
+
+ SilcPublicKey public_key; /* Public key of user, set by application */
+ SilcPrivateKey private_key; /* Private key of user, set by application */
+ SilcPKCS pkcs; /* PKCS allocated by application */
+
+ /*
+ * The following fields are set by the library
+ */
+
+ /* Scheduler, set by library. Application may use this pointer. */
+ SilcSchedule schedule;
+
+ /* Random Number Generator. Application should use this as its primary
+ random number generator. */
+ SilcRng rng;
+
+ /* Application specific user data pointer. Client library does not
+ touch this. This the context sent as argument to silc_client_alloc.
+ Application can use it freely. */
+ void *application;
+
+ /* Generic hash context for application usage */
+ SilcHash md5hash;
+ SilcHash sha1hash;
+
+ /* Internal data for client library. Application cannot access this
+ data at all. */
+ SilcClientInternal internal;
+};
+/***/
+
+/****s* silcclient/SilcClientAPI/SilcClientConnection
+ *
+ * NAME
+ *
+ * typedef struct SilcClientConnectionStruct { ... }
+ * *SilcClientConnection
+ *
+ * DESCRIPTION
+ *
+ * This structure represents a connection. When connection is created
+ * to server this is context is returned to the application in the
+ * "connected" client operation. It includes all the important
+ * data for the session, such as nickname, local and remote IDs, and
+ * other information.
+ *
+ * SOURCE
+ */
+struct SilcClientConnectionStruct {
+ /*
+ * Local data
+ */
+ char *nickname; /* Current nickname */
+ SilcClientEntry local_entry; /* Own Client Entry */
+ SilcClientID *local_id; /* Current Client ID */
+ unsigned char *local_id_data; /* Current Client ID decoded */
+ SilcUInt32 local_id_data_len;
+
+ /*
+ * Remote data
+ */
+ char *remote_host; /* Remote host name */
+ int remote_port; /* Remote port */
+ SilcServerID *remote_id; /* Remote Server ID */
+ unsigned char *remote_id_data; /* Remote Server ID decoded */
+ SilcUInt32 remote_id_data_len;
+
+ /*
+ * Common data
+ */
+
+ /* User data context. Library does not touch this. Application may
+ freely set and use this pointer for its needs. */
+ void *context;
+
+ /* Pointer back to the SilcClient. Application may use this. */
+ SilcClient client;
+
+ /* Current channel. Application may use and set this pointer if needed. */
+ SilcChannelEntry current_channel;
+
+ /* Socket connection object for this connection. Application may
+ use this if needed. The sock->user_data is back pointer to this
+ structure. */
+ SilcSocketConnection sock;
+
+ /* Current command identifier, 0 not used */
+ SilcUInt16 cmd_ident;
+
+ /* Internal data for client library. Application cannot access this
+ data at all. */
+ SilcClientConnectionInternal internal;
+};
+/***/
+
/****d* silcclient/SilcClientAPI/SilcKeyAgreementStatus
*
* NAME
SilcClientConnection conn,
char *message);
-
/****f* silcclient/SilcClientAPI/SilcConnectionAuthRequest
*
* SYNOPSIS
SilcUInt32 data_len,
bool force_send);
-#include "client.h"
#include "command.h"
#include "command_reply.h"
#include "idlist.h"