Fixed channel reference counting.
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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
silc_fsm_free(fsm);
}
-
/* Packet FSM thread destructor */
static void silc_client_packet_destructor(SilcFSMThread thread,
case SILC_PACKET_KEY_EXCHANGE_2:
case SILC_PACKET_REKEY_DONE:
case SILC_PACKET_CONNECTION_AUTH:
- case SILC_PACKET_CONNECTION_AUTH_REQUEST:
return FALSE;
break;
}
case SILC_PACKET_FTP:
/* File transfer packet */
- // silc_client_ftp(client, conn, packet);
+// silc_fsm_next(fsm, silc_client_ftp);
break;
case SILC_PACKET_CHANNEL_KEY:
break;
case SILC_PACKET_CONNECTION_AUTH_REQUEST:
- /* Reply to connection authentication request to resolve authentication
- method from server. */
- // silc_client_connection_auth_request(client, conn, packet);
+ /** Connection auth resolve reply */
+ silc_fsm_next(fsm, silc_client_connect_auth_request);
break;
case SILC_PACKET_REKEY:
silc_packet_stream_destroy(conn->stream);
SILC_LOG_DEBUG(("Finishing connection machine"));
-
SILC_FSM_FINISH;
}
}
}
-#if 0
-/* Processes incoming connection authentication method request packet.
- It is a reply to our previously sent request. The packet can be used
- to resolve the authentication method for the current session if the
- client does not know it beforehand. */
-
-void silc_client_connection_auth_request(SilcClient client,
- SilcClientConnection conn,
- SilcPacketContext *packet)
-{
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcUInt16 conn_type, auth_meth;
- int ret;
-
- /* If we haven't send our request then ignore this one. */
- if (!conn->internal->connauth)
- return;
-
- /* Parse the payload */
- ret = silc_buffer_unformat(packet->buffer,
- SILC_STR_UI_SHORT(&conn_type),
- SILC_STR_UI_SHORT(&auth_meth),
- SILC_STR_END);
- if (ret == -1)
- auth_meth = SILC_AUTH_NONE;
-
- /* Call the request callback to notify application for received
- authentication method information. */
- if (conn->internal->connauth->callback)
- (*conn->internal->connauth->callback)(client, conn, auth_meth,
- conn->internal->connauth->context);
-
- silc_schedule_task_del(client->schedule, conn->internal->connauth->timeout);
-
- silc_free(conn->internal->connauth);
- conn->internal->connauth = NULL;
-}
-
-/* Timeout task callback called if the server does not reply to our
- connection authentication method request in the specified time interval. */
-
-SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
-{
- SilcClientConnection conn = (SilcClientConnection)context;
- SilcClient client = conn->client;
-
- if (!conn->internal->connauth)
- return;
-
- /* Call the request callback to notify application */
- if (conn->internal->connauth->callback)
- (*conn->internal->connauth->callback)(client, conn, SILC_AUTH_NONE,
- conn->internal->connauth->context);
-
- silc_free(conn->internal->connauth);
- conn->internal->connauth = NULL;
-}
-
-/* This function can be used to request the current authentication method
- from the server. This may be called when connecting to the server
- and the client library requests the authentication data from the
- application. If the application does not know the current authentication
- method it can request it from the server using this function.
- The `callback' with `context' will be called after the server has
- replied back with the current authentication method. */
-
-void
-silc_client_request_authentication_method(SilcClient client,
- SilcClientConnection conn,
- SilcConnectionAuthRequest callback,
- void *context)
-{
- SilcClientConnAuthRequest connauth;
- SilcBuffer packet;
-
- assert(client && conn);
- connauth = silc_calloc(1, sizeof(*connauth));
- connauth->callback = callback;
- connauth->context = context;
-
- if (conn->internal->connauth)
- silc_free(conn->internal->connauth);
-
- conn->internal->connauth = connauth;
-
- /* Assemble the request packet and send it to the server */
- packet = silc_buffer_alloc(4);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
- silc_buffer_format(packet,
- SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
- SILC_STR_UI_SHORT(SILC_AUTH_NONE),
- SILC_STR_END);
- silc_client_packet_send(client, conn->sock,
- SILC_PACKET_CONNECTION_AUTH_REQUEST,
- NULL, 0, NULL, NULL,
- packet->data, packet->len, FALSE);
- silc_buffer_free(packet);
-
- /* Register a timeout in case server does not reply anything back. */
- connauth->timeout =
- silc_schedule_task_add(client->schedule, conn->sock->sock,
- silc_client_request_authentication_method_timeout,
- conn,
- client->internal->params->connauth_request_secs, 0,
- SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-}
-#endif /* 0 */
-
/* Allocates new client object. This has to be done before client may
work. After calling this one must call silc_client_init to initialize
the client. The `application' is application specific user data pointer
if (params)
memcpy(new_client->internal->params, params, sizeof(*params));
- if (!new_client->internal->params->connauth_request_secs)
- new_client->internal->params->connauth_request_secs = 2;
-
new_client->internal->params->
nickname_format[sizeof(new_client->internal->
params->nickname_format) - 1] = 0;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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
typedef struct SilcChannelUserStruct *SilcChannelUser;
typedef struct SilcClientInternalStruct *SilcClientInternal;
typedef struct SilcClientConnectionInternalStruct
- *SilcClientConnectionInternal;
+ *SilcClientConnectionInternal;
typedef struct SilcChannelPrivateKeyStruct *SilcChannelPrivateKey;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004, 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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 (silc_client_on_channel(channel, client_entry))
return TRUE;
+ SILC_LOG_DEBUG(("Add client %s to channel", client_entry->nickname));
+
chu = silc_calloc(1, sizeof(*chu));
if (!chu)
return FALSE;
if (!chu)
return FALSE;
+ SILC_LOG_DEBUG(("Remove client %s from channel", client_entry->nickname));
+
silc_hash_table_del(chu->client->channels, chu->channel);
silc_hash_table_del(chu->channel->user_list, chu->client);
silc_free(chu);
+ /* If channel became empty, delete it */
+ if (!silc_hash_table_count(channel->user_list))
+ silc_client_del_channel(client, conn, channel);
+
silc_client_unref_client(client, conn, client_entry);
silc_client_unref_channel(client, conn, channel);
SilcHashTableList htl;
SilcChannelUser chu;
+ if (!silc_hash_table_count(client_entry->channels))
+ return;
+
+ SILC_LOG_DEBUG(("Remove client from all joined channels"));
+
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);
+
+ /* If channel became empty, delete it */
+ if (!silc_hash_table_count(chu->channel->user_list))
+ silc_client_del_channel(client, conn, chu->channel);
+
silc_client_unref_client(client, conn, chu->client);
silc_client_unref_channel(client, conn, chu->channel);
silc_free(chu);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2006 Pekka Riikonen
+ Copyright (C) 2006 - 2007 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
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2006 Pekka Riikonen
+ Copyright (C) 2006 - 2007 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
/* Callback called by application to return authentication data */
-static void silc_client_connect_auth_method(SilcBool success,
- SilcAuthMethod auth_meth,
+static void silc_client_connect_auth_method(SilcAuthMethod auth_meth,
void *auth, SilcUInt32 auth_len,
void *context)
{
SilcFSMThread fsm = context;
SilcClientConnection conn = silc_fsm_get_context(fsm);
- conn->internal->params.auth_method = SILC_AUTH_NONE;
-
- if (success) {
- conn->internal->params.auth_method = auth_meth;
- conn->internal->params.auth = auth;
- conn->internal->params.auth_len = auth_len;
- }
+ conn->internal->params.auth_method = auth_meth;
+ conn->internal->params.auth = auth;
+ conn->internal->params.auth_len = auth_len;
SILC_FSM_CALL_CONTINUE(fsm);
}
SILC_FSM_CALL_CONTINUE(fsm);
}
+/********************** CONNECTION_AUTH_REQUEST packet **********************/
+
+/* Received connection authentication request packet. We get the
+ required authentication method here. */
+
+SILC_FSM_STATE(silc_client_connect_auth_request)
+{
+ SilcClientConnection conn = fsm_context;
+ SilcPacket packet = state_context;
+ SilcUInt16 conn_type, auth_meth;
+
+ if (!conn->internal->auth_request) {
+ silc_packet_free(packet);
+ SILC_FSM_FINISH;
+ }
+
+ /* Parse the payload */
+ if (silc_buffer_unformat(&packet->buffer,
+ SILC_STR_UI_SHORT(&conn_type),
+ SILC_STR_UI_SHORT(&auth_meth),
+ SILC_STR_END) < 0)
+ auth_meth = SILC_AUTH_NONE;
+
+ silc_packet_free(packet);
+
+ SILC_LOG_DEBUG(("Resolved authentication method: %s",
+ (auth_meth == SILC_AUTH_NONE ? "none" :
+ auth_meth == SILC_AUTH_PASSWORD ? "passphrase" :
+ "public key")));
+ conn->internal->params.auth_method = auth_meth;
+
+ /* Continue authentication */
+ silc_fsm_continue_sync(&conn->internal->event_thread);
+ SILC_FSM_FINISH;
+}
+
/*************************** Connect remote host ****************************/
/* Connection timeout callback */
silc_fsm_next(fsm, silc_client_st_connect_setup_udp);
else
/** Run key exchange (TCP) */
- silc_fsm_next(fsm, silc_client_st_connect_auth);
+ silc_fsm_next(fsm, silc_client_st_connect_auth_resolve);
SILC_FSM_CALL(conn->internal->op = silc_ske_initiator(conn->internal->ske,
conn->stream,
silc_stream_destroy(old);
/** Start authentication */
- silc_fsm_next(fsm, silc_client_st_connect_auth);
+ silc_fsm_next(fsm, silc_client_st_connect_auth_resolve);
SILC_FSM_CONTINUE;
}
-/* Get authentication method to be used in authentication protocol */
+/* Resolved authentication method to be used in authentication protocol */
+
+SILC_FSM_STATE(silc_client_st_connect_auth_resolve)
+{
+ SilcClientConnection conn = fsm_context;
+
+ SILC_LOG_DEBUG(("Resolve authentication method"));
+
+ if (conn->internal->disconnected) {
+ /** Disconnected */
+ silc_fsm_next(fsm, silc_client_st_connect_error);
+ SILC_FSM_CONTINUE;
+ }
+
+ /* If authentication method and data is set, use them */
+ if (conn->internal->params.auth_set) {
+ /** Got authentication data */
+ silc_fsm_next(fsm, silc_client_st_connect_auth_start);
+ SILC_FSM_CONTINUE;
+ }
+
+ /* Send connection authentication request packet */
+ silc_packet_send_va(conn->stream,
+ SILC_PACKET_CONNECTION_AUTH_REQUEST, 0,
+ SILC_STR_UI_SHORT(SILC_CONN_CLIENT),
+ SILC_STR_UI_SHORT(SILC_AUTH_NONE),
+ SILC_STR_END);
+
+ /** Wait for authentication method */
+ conn->internal->auth_request = TRUE;
+ conn->internal->params.auth_method = SILC_AUTH_NONE;
+ silc_fsm_next_later(fsm, silc_client_st_connect_auth_data, 2, 0);
+ SILC_FSM_WAIT;
+}
+
+/* Get authentication data to be used in authentication protocol */
-SILC_FSM_STATE(silc_client_st_connect_auth)
+SILC_FSM_STATE(silc_client_st_connect_auth_data)
{
SilcClientConnection conn = fsm_context;
SilcClient client = conn->client;
SILC_FSM_CONTINUE;
}
- silc_fsm_next(fsm, silc_client_st_connect_auth_start);
+ conn->internal->auth_request = FALSE;
- /* If authentication data not provided, ask from application */
- if (!conn->internal->params.auth_set)
- SILC_FSM_CALL(client->internal->ops->get_auth_method(
+ /** Get authentication data */
+ silc_fsm_next(fsm, silc_client_st_connect_auth_start);
+ SILC_FSM_CALL(client->internal->ops->get_auth_method(
client, conn,
conn->remote_host,
conn->remote_port,
+ conn->internal->params.auth_method,
silc_client_connect_auth_method, fsm));
-
- if (conn->internal->params.auth_method == SILC_AUTH_PUBLIC_KEY)
- conn->internal->params.auth = conn->private_key;
-
- /* We have authentication data */
- SILC_FSM_CONTINUE;
}
/* Start connection authentication with remote host */
SILC_FSM_CONTINUE;
}
+ /* We always use the same key for connection authentication and SKE */
+ if (conn->internal->params.auth_method == SILC_AUTH_PUBLIC_KEY)
+ conn->internal->params.auth = conn->private_key;
+
/* Allocate connection authentication protocol */
connauth = silc_connauth_alloc(conn->internal->schedule,
conn->internal->ske,
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2006 Pekka Riikonen
+ Copyright (C) 2006 - 2007 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
#ifndef CLIENT_CONNECT_H
#define CLIENT_CONNECT_H
-/* States */
+SILC_FSM_STATE(silc_client_connect_auth_request);
SILC_FSM_STATE(silc_client_st_connect);
SILC_FSM_STATE(silc_client_st_connect_set_stream);
SILC_FSM_STATE(silc_client_st_connect_key_exchange);
SILC_FSM_STATE(silc_client_st_connect_setup_udp);
-SILC_FSM_STATE(silc_client_st_connect_auth);
+SILC_FSM_STATE(silc_client_st_connect_auth_resolve);
+SILC_FSM_STATE(silc_client_st_connect_auth_data);
SILC_FSM_STATE(silc_client_st_connect_auth_start);
SILC_FSM_STATE(silc_client_st_connected);
SILC_FSM_STATE(silc_client_st_connect_error);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2004 Pekka Riikonen
+ Copyright (C) 2001 - 2007 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
session->filepath = strdup(filepath);
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_strncat(path, strlen(filepath) + 9, filepath, strlen(filepath));
+ silc_asprintf(&path, "file://%s", filepath);
/* Allocate memory filesystem and put the file to it */
if (strrchr(path, '/'))
return SILC_CLIENT_FILE_OK;
}
-/* Callback called after remote client information has been resolved.
- This will try to find existing session for the client entry. If found
- then continue with the key agreement protocol. If not then it means
- this is a file transfer request and we let the application know. */
+/************************** FTP Request Processing **************************/
-static void silc_client_ftp_resolve_cb(SilcClient client,
- SilcClientConnection conn,
- SilcClientEntry *clients,
- SilcUInt32 clients_count,
- void *context)
+/* Client resolving callback. Continues with the FTP processing */
+
+static void silc_client_ftp_client_resolved(SilcClient client,
+ SilcClientConnection conn,
+ SilcStatus status,
+ SilcDList clients,
+ void *context)
{
- SilcPacketContext *packet = (SilcPacketContext *)context;
- SilcClientFtpSession session;
- SilcKeyAgreementPayload payload = NULL;
- SilcClientEntry client_entry;
+ SilcFSMThread thread = context;
+ SilcPacket packet = silc_fsm_get_state_context(thread);
+
+ /* If no client found, ignore the packet, a silent error */
+ if (!clients) {
+ silc_packet_free(packet);
+ silc_fsm_finish(thread);
+ return;
+ }
+
+ /* Continue processing the packet */
+ SILC_FSM_CALL_CONTINUE(context);
+}
+
+/* Received file transfer packet. Only file transfer requests get here.
+ The actual file transfer is handled by the SFTP library when we give it
+ the packet stream wrapped into SilcStream context. */
+
+SILC_FSM_STATE(silc_client_ftp)
+{
+ SilcClientConnection conn = fsm_context;
+ SilcClient client = conn->client;
+ SilcPacket packet = state_context;
+ SilcClientID remote_id;
+ SilcClientEntry remote_client;
+ SilcKeyAgreementPayload payload;
+ SilcUInt8 type;
char *hostname;
SilcUInt16 port;
+ int ret;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Process file transfer packet"));
+
+ if (silc_buffer_len(&packet->buffer) < 1)
+ goto out;
- if (!clients)
+ /* We support file transfer type number 1 (== SFTP) */
+ if (packet->buffer.data[0] != 0x01) {
+ SILC_LOG_DEBUG(("Unsupported file transfer type %d",
+ packet->buffer.data[0]));
goto out;
+ }
+
+ if (!silc_id_str2id(packet->src_id, packet->src_id_len,
+ SILC_ID_CLIENT, &remote_id, sizeof(remote_id))) {
+ SILC_LOG_DEBUG(("Invalid client ID"));
+ goto out;
+ }
+
+ /* Check whether we know this client already */
+ remote_client = silc_client_get_client_by_id(client, conn, &remote_id);
+ if (!remote_client || !remote_client->nickname[0]) {
+ /** Resolve client info */
+ silc_client_unref_client(client, conn, remote_client);
+ SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
+ client, conn, &remote_id, NULL,
+ silc_client_ftp_client_resolved,
+ fsm));
+ /* NOT REACHED */
+ }
- client_entry = clients[0];
silc_dlist_start(conn->internal->ftp_sessions);
while ((session = silc_dlist_get(conn->internal->ftp_sessions))
}
/* Parse the key agreement payload */
- payload = silc_key_agreement_payload_parse(packet->buffer->data,
- packet->buffer->len);
- if (!payload)
+ payload = silc_key_agreement_payload_parse(packet->buffer->data + 1,
+ packet->buffer->len - 1);
+ if (!payload) {
+ SILC_LOG_DEBUG(("Invalid key agreement payload"));
goto out;
+ }
hostname = silc_key_agreement_get_hostname(payload);
port = silc_key_agreement_get_port(payload);
session->filepath, session->monitor_context);
}
- out:
- if (payload)
- silc_key_agreement_payload_free(payload);
- silc_packet_context_free(packet);
-}
-
-/* Called when file transfer packet is received. This will parse the
- packet and give it to the file transfer protocol. */
-
-void silc_client_ftp(SilcClient client,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
-{
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcUInt8 type;
- int ret;
-
- SILC_LOG_DEBUG(("Start"));
-
- /* Parse the payload */
- ret = silc_buffer_unformat(packet->buffer,
- SILC_STR_UI_CHAR(&type),
- SILC_STR_END);
- if (ret == -1)
- return;
-
- /* We support only type number 1 (== SFTP) */
- if (type != 1)
- return;
- silc_buffer_pull(packet->buffer, 1);
- /* If we have active FTP session then give the packet directly to the
- protocol processor. */
- if (conn->internal->active_session) {
- /* Give it to the SFTP */
- 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->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. */
- SilcClientID *remote_id;
-
- if (packet->src_id_type != SILC_ID_CLIENT)
- return;
-
- remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- SILC_ID_CLIENT);
- if (!remote_id)
- return;
-
- /* Resolve the client */
- silc_client_get_client_by_id_resolve(client, sock->user_data, remote_id,
- NULL, silc_client_ftp_resolve_cb,
- silc_packet_context_dup(packet));
- silc_free(remote_id);
- }
+ out:
+ silc_packet_free(packet);
+ SILC_FSM_FINISH;
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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
void *completion_context;
} *VerifyKeyContext;
-/* 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;
- SilcBool pfs;
- SilcUInt32 timeout;
- void *context;
-} *SilcClientRekey;
-
-/* Internal context for connection process. This is needed as we
- doing asynchronous connecting. */
-typedef struct {
- SilcClient client;
- SilcClientConnection conn;
- SilcTask task;
- int sock;
- char *host;
- int port;
- void *context;
-} SilcClientInternalConnectContext;
-
/* Structure to hold away messages set by user. This is mainly created
for future extensions where away messages could be set according filters
such as nickname and hostname. For now only one away message can
SilcClientConnectionParams params; /* Connection parameters */
SilcFSMStruct fsm; /* Connection FSM */
SilcFSMThreadStruct event_thread; /* FSM thread for events */
- SilcFSMEventStruct wait_event; /* Event signaller */
+ SilcFSMEventStruct wait_event; /* Event signaller */
SilcSchedule schedule; /* Connection's scheduler */
SilcMutex lock; /* Connection lock */
SilcSKE ske; /* Key exchange protocol */
SilcBuffer remote_idp; /* Remote ID Payload */
SilcAsyncOperation op; /* Protocols async operation */
SilcAsyncOperation cop; /* Async operation for application */
+ SilcHashTable attrs; /* Configured user attributes */
SilcIDCache client_cache; /* Client entry cache */
SilcIDCache channel_cache; /* Channel entry cache */
unsigned int registering : 1; /* Set when registering to network */
unsigned int rekey_responder : 1; /* Set when rekeying as responder */
unsigned int callback_called : 1; /* Set when connect callback called */
+ unsigned int auth_request : 1; /* Set when requesting auth method */
SilcClientAway *away;
- SilcClientConnAuthRequest connauth;
SilcDList ftp_sessions;
SilcUInt32 next_session_id;
SilcClientFtpSession active_session;
- SilcHashTable attrs;
SilcHashTable privmsg_wait; /* Waited private messages */
};
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2006 Pekka Riikonen
+ Copyright (C) 2001 - 2007 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
silc_client_keyagr_free(client, conn, client_entry);
}
-/* Starts key agreement as responder. */
+/* Starts key agreement as responder. */
static void silc_client_process_key_agreement(SilcClient client,
SilcClientConnection conn,
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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
/* Continue after last command reply received */
if (SILC_STATUS_IS_ERROR(status) || status == SILC_STATUS_OK ||
status == SILC_STATUS_LIST_END)
- SILC_FSM_CALL_CONTINUE(notify->fsm);
+ SILC_FSM_CALL_CONTINUE_SYNC(notify->fsm);
return TRUE;
}
SilcClient client = conn->client;
SilcClientNotify notify = state_context;
SilcNotifyPayload payload = notify->payload;
+ SilcPacket packet = notify->packet;
SilcNotifyType type = silc_notify_get_type(payload);
SilcArgumentPayload args = silc_notify_get_args(payload);
SilcClientEntry client_entry;
- unsigned char *tmp;
+ SilcChannelEntry channel;
+ unsigned char *tmp;
SilcUInt32 tmp_len;
SilcID id;
/* Notify application */
NOTIFY(client, conn, type, client_entry, tmp);
+ /* Remove from channel */
+ if (packet->dst_id_type == SILC_ID_CHANNEL) {
+ if (silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
+ &id.u.channel_id, sizeof(id.u.channel_id))) {
+ channel = silc_client_get_channel_by_id(client, conn, &id.u.channel_id);
+ if (channel) {
+ silc_client_remove_from_channel(client, conn, channel, client_entry);
+ silc_client_unref_channel(client, conn, channel);
+ }
+ }
+ }
+
/* Delete client */
- silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
silc_client_unref_client(client, conn, client_entry);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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 (status != SILC_STATUS_OK)
silc_fsm_next(&cmd->thread, silc_client_command_continue_error);
- if (clients)
- silc_dlist_uninit(clients);
-
/* Continue with the command */
SILC_FSM_CALL_CONTINUE(&cmd->thread);
}
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
- SilcChannelEntry channel;
+ SilcClient client = conn->client;
+ SilcChannelEntry channel = NULL;
SilcBuffer idp = NULL;
if (cmd->argc == 2) {
1, 1, silc_buffer_datalen(idp));
silc_buffer_free(idp);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
+ SilcClient client = conn->client;
SilcChannelEntry channel;
SilcBuffer idp;
char *name;
1, silc_buffer_datalen(idp));
silc_buffer_free(idp);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
SilcClientEntry client_entry = NULL;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcBuffer clidp, chidp, args = NULL;
SilcPublicKey pubkey = NULL;
SilcDList clients = NULL;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
silc_buffer_free(args);
silc_free(nickname);
silc_client_list_free(client, conn, clients);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
- SilcChannelEntry channel;
+ SilcClient client = conn->client;
+ SilcChannelEntry channel = NULL;
SilcBuffer auth = NULL, cauth = NULL;
char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
int i, passphrase_len = 0;
if (passphrase)
memset(passphrase, 0, strlen(passphrase));
silc_free(passphrase);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
SILC_FSM_FINISH;
}
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcBuffer chidp, auth = NULL, pk = NULL;
unsigned char *name, *cp, modebuf[4], tmp[4], *arg = NULL;
SilcUInt32 mode, add, type, len, arg_len = 0;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
silc_buffer_free(chidp);
silc_buffer_free(auth);
silc_buffer_free(pk);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
SILC_FSM_FINISH;
}
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcChannelUser chu;
SilcClientEntry client_entry;
SilcBuffer clidp, chidp, auth = NULL;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
silc_buffer_free(auth);
silc_free(nickname);
silc_client_list_free(client, conn, clients);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
silc_client_list_free(client, conn, clients);
silc_free(nickname);
SILC_FSM_FINISH;
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcBuffer idp, idp2;
SilcClientEntry target;
SilcDList clients = NULL;
silc_buffer_free(idp2);
silc_free(nickname);
silc_client_list_free(client, conn, clients);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
silc_free(nickname);
SILC_FSM_FINISH;
}
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
+ SilcClient client = conn->client;
SilcChannelEntry channel;
SilcBuffer chidp, args = NULL;
char *name, *ban = NULL;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
silc_buffer_free(chidp);
silc_buffer_free(args);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
+ SilcClient client = conn->client;
SilcChannelEntry channel;
SilcBuffer idp;
char *name;
if (conn->current_channel == channel)
conn->current_channel = NULL;
+ silc_client_unref_channel(client, conn, channel);
+
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
SILC_FSM_CONTINUE;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 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 (conn->internal->disconnected) {
SILC_LOG_DEBUG(("Command %s canceled", silc_get_command_name(cmd->cmd)));
silc_list_del(conn->internal->pending_commands, cmd);
+ if (!cmd->called)
+ ERROR_CALLBACK(SILC_STATUS_ERR_TIMEDOUT);
SILC_FSM_FINISH;
}
/* Notify application */
silc_client_command_callback(cmd, client_entry);
- /* Remove the client from all channels and free it */
+ /* Remove the client */
if (client_entry) {
silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
SilcUInt16 idp_len, mode;
SilcHashTableList htl;
SilcBufferStruct client_id_list, client_mode_list;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcClientEntry client_entry;
SilcID id;
int i;
/* Resolve users we do not know about */
if (!cmd->resolved) {
cmd->resolved = TRUE;
+ silc_client_unref_channel(client, conn, channel);
SILC_FSM_CALL(silc_client_get_clients_by_list(
client, conn, list_count, &client_id_list,
silc_client_command_reply_users_resolved, cmd));
silc_hash_table_list_reset(&htl);
out:
+ silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_command_reply_processed);
SILC_FSM_CONTINUE;
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2000 - 2006 Pekka Riikonen
+ Copyright (C) 2000 - 2007 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
*
* DESCRIPTION
*
- * Authentication method resolving callback. This is called by the
- * application to return the resolved authentication method. The client
+ * Authentication data resolving callback. This is called by the
+ * application to return the resolved authentication data. The client
* library has called the get_auth_method client operation and given
- * this function pointer as argument. The `success' will indicate whether
- * the authentication method could be resolved. The `auth_meth' is the
- * resolved authentication method. The `auth_data' and the `auth_data_len'
+ * this function pointer as argument. The `auth_meth' is the selected
+ * authentication method. The `auth_data' and the `auth_data_len'
* are the resolved authentication data. The `context' is the libary's
* context sent to the get_auth_method client operation.
*
+ * If the `auth_method' is SILC_AUTH_PASSWORD then `auth' and `auth_len'
+ * is the passphrase and its length. If it is SILC_AUTH_PUBLIC_KEY the
+ * `auth' must be NULL. The library will use the private key given as
+ * argument to silc_client_connect_to_server, silc_client_connect_to_client
+ * or silc_client_key_exchange. If it is SILC_AUTH_NONE, both `auth' and
+ * `auth_len' are ignored.
+ *
***/
-typedef void (*SilcGetAuthMeth)(SilcBool success,
- SilcAuthMethod auth_meth,
+typedef void (*SilcGetAuthMeth)(SilcAuthMethod auth_meth,
void *auth, SilcUInt32 auth_len,
void *context);
SilcStatus error, va_list ap);
/* Find authentication method and authentication data by hostname and
- port. The hostname may be IP address as well. When the authentication
- method has been resolved the `completion' callback with the found
- authentication method and authentication data is called. The `conn'
- may be NULL. */
+ port. The hostname may be IP address as well. The `auth_method' is
+ the authentication method the remote connection requires. It is
+ however possible that remote accepts also some other authentication
+ method. Application should use the method that may have been
+ configured for this connection. If none has been configured it should
+ use the required `auth_method'. If the `auth_method' is
+ SILC_AUTH_NONE, server does not require any authentication or the
+ required authentication method is not known. The `completion'
+ callback must be called to deliver the chosen authentication method
+ and data. The `conn' may be NULL. */
void (*get_auth_method)(SilcClient client, SilcClientConnection conn,
char *hostname, SilcUInt16 port,
+ SilcAuthMethod auth_method,
SilcGetAuthMeth completion, void *context);
/* Verifies received public key. The `conn_type' indicates which entity
- (server, client etc.) has sent the public key. If user decides to trust
- the application may save the key as trusted public key for later
- use. The `completion' must be called after the public key has been
- verified. */
+ (server or client) has sent the public key. If user decides to trust
+ the key the application may save the key as trusted public key for
+ later use. The `completion' must be called after the public key has
+ been verified. */
void (*verify_public_key)(SilcClient client, SilcClientConnection conn,
SilcConnectionType conn_type,
SilcPublicKey public_key,
in the callbacks to protect application specific data. */
SilcBool threads;
- /* Connection authentication method request timeout. If server does not
- reply back the current authentication method when we've requested it
- in this time interval we'll assume the reply will not come at all.
- If set to zero, the default value (2 seconds) will be used. */
- unsigned int connauth_request_secs;
-
/* Nickname format string. This can be used to order the client library
to save the nicknames in the library in a certain format. Since
nicknames are not unique in SILC it is possible to have multiple same
* silc_client_connect_to_server(SilcClient client,
* SilcClientConnectionParams *params,
* SilcPublicKey public_key,
+ * SilcPrivateKey private_key,
* char *remote_host, int port,
* SilcClientConnectCallback callback,
* void *context);
* silc_client_connect_to_client(SilcClient client,
* SilcClientConnectionParams *params,
* SilcPublicKey public_key,
+ * SilcPrivateKey private_key,
* char *remote_host, int port,
* SilcClientConnectCallback callback,
* void *context);
* DESCRIPTION
*
* Returns list of private keys associated to the `channel'. The caller
- * must free the returned list. The pointers in the list may be
- * used to delete the specific key by giving the pointer as argument to the
- * function silc_client_del_channel_private_key. Each entry in the list
- * is SilcChannelPrivateKey.
+ * must free the returned list with silc_dlist_uninit. The pointers in
+ * the list may be used to delete the specific key by giving the pointer
+ * as argument to the function silc_client_del_channel_private_key. Each
+ * entry in the list is SilcChannelPrivateKey.
*
***/
SilcDList silc_client_list_channel_private_keys(SilcClient client,
SilcClientConnection conn,
char *message);
-/****f* silcclient/SilcClientAPI/SilcConnectionAuthRequest
- *
- * SYNOPSIS
- *
- * typedef void (*SilcConnectionAuthRequest)(SilcClient client,
- * SilcClientConnection conn,
- * SilcAuthMethod auth_meth,
- * void *context);
- *
- * DESCRIPTION
- *
- * Connection authentication method request callback. This is called
- * by the client library after it has received the authentication method
- * that the application requested by calling the function
- * silc_client_request_authentication_method.
- *
- ***/
-typedef void (*SilcConnectionAuthRequest)(SilcClient client,
- SilcClientConnection conn,
- SilcAuthMethod auth_meth,
- void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_request_authentication_method
- *
- * SYNOPSIS
- *
- * void
- * silc_client_request_authentication_method(SilcClient client,
- * SilcClientConnection conn,
- * SilcConnectionAuthRequest
- * callback,
- * void *context);
- *
- * DESCRIPTION
- *
- * This function can be used to request the current authentication method
- * from the server. This may be called when connecting to the server
- * and the client library requests the authentication data from the
- * application. If the application does not know the current authentication
- * method it can request it from the server using this function.
- * The `callback' with `context' will be called after the server has
- * replied back with the current authentication method.
- *
- ***/
-void
-silc_client_request_authentication_method(SilcClient client,
- SilcClientConnection conn,
- SilcConnectionAuthRequest callback,
- void *context);
-
/****d* silcclient/SilcClientAPI/SilcClientMonitorStatus
*
* NAME