fixed private message routing, and myriad other fixes.
else
silc_schedule_task_add_timeout(server->schedule,
silc_server_command_process_timeout,
- timeout, 0, 1);
+ timeout, 0, 0);
return;
}
/* Truncate over long nicks */
if (nick_len > 128) {
- nick[128] = '\0';
nick_len = 128;
+ nick[nick_len - 1] = '\0';
}
/* Check for valid nickname string. This is cached, original is saved
oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- /* Remove old cache entry */
- silc_idcache_del_by_context(server->local_list->clients, client, NULL);
-
- silc_free(client->id);
- client->id = new_id;
-
+ /* Update client entry */
+ silc_idcache_update_by_context(server->local_list->clients, client,
+ new_id, nickc, TRUE);
+ silc_free(new_id);
silc_free(client->nickname);
client->nickname = strdup(nick);
- /* Update client cache */
- silc_idcache_add(server->local_list->clients, nickc,
- client->id, (void *)client);
-
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Send NICK_CHANGE notify to the client's channels */
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcID id;
+ SilcChannelID *channel_id = NULL;
SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
SilcUInt32 lch_count = 0, gch_count = 0;
}
/* Get Channel ID */
- if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
- SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
- goto out;
- }
+ if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
+ channel_id = SILC_ID_GET_ID(id);
/* Get the channels from local list */
- lchannels = silc_idlist_get_channels(server->local_list, SILC_ID_GET_ID(id),
+ lchannels = silc_idlist_get_channels(server->local_list, channel_id,
&lch_count);
/* Get the channels from global list */
- gchannels = silc_idlist_get_channels(server->global_list, SILC_ID_GET_ID(id),
+ gchannels = silc_idlist_get_channels(server->global_list, channel_id,
&gch_count);
/* Send the reply */
goto out;
}
+ SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
+ id.type)));
+
/* The ID must be ours */
if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
if (!channel)
return;
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
/* Get the client entry */
if (idata->conn_type == SILC_CONN_CLIENT) {
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
- silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+ NULL, &hostname, &ip, NULL);
/* Get the username */
username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
- silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+ NULL, &hostname, &ip, NULL);
if (server->server_type != SILC_ROUTER) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
SilcUInt32 mode = 0, len, len2, id_len, flen;
const char *hostname, *ip;
- silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+ NULL, &hostname, &ip, NULL);
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
int global = FALSE;
const char *hostname, *ip;
- silc_socket_stream_get_info(cmd->sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+ NULL, &hostname, &ip, NULL);
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
void silc_idlist_add_data(void *entry, SilcIDListData idata)
{
SilcIDListData data = entry;
+ data->conn_type = idata->conn_type;
+ data->sconn = idata->sconn;
data->hash = idata->hash;
data->public_key = idata->public_key;
memcpy(data->fingerprint, idata->fingerprint, sizeof(data->fingerprint));
server = id_cache->context;
sock = server->connection;
- if (sock && silc_socket_stream_get_info(sock, NULL, &host, &ip, NULL)) {
+ if (sock && silc_socket_stream_get_info(
+ silc_packet_stream_get_stream(sock),
+ NULL, &host, &ip, NULL)) {
if (((host && !strcasecmp(host, hostname)) ||
(ip && !strcasecmp(ip, hostname))) &&
server->id->port == SILC_SWAB_16(port))
SILC_LOG_DEBUG(("Start"));
if (entry) {
- if (!silc_idcache_del_by_context(id_list->clients, entry, NULL /* XXX */)) {
+ /* Delete client, destructor will free data */
+ if (!silc_idcache_del_by_context(id_list->clients, entry, NULL)) {
SILC_LOG_DEBUG(("Unknown client, did not delete"));
return FALSE;
}
-
- assert(!silc_hash_table_count(entry->channels));
-
- silc_free(entry->nickname);
- silc_free(entry->servername);
- silc_free(entry->username);
- silc_free(entry->userinfo);
- silc_free(entry->id);
- silc_free(entry->attrs);
- silc_hash_table_free(entry->channels);
-
- memset(entry, 'F', sizeof(*entry));
- silc_free(entry);
-
return TRUE;
}
SilcPacket packet)
{
silc_server_notify_process(server, sock, packet, &packet->buffer);
+ silc_packet_free(packet);
}
void silc_server_notify_list(SilcServer server,
silc_buffer_pull(&packet->buffer, len);
}
+ silc_packet_free(packet);
silc_buffer_free(buffer);
}
if (packet->src_id_type != SILC_ID_CLIENT ||
packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id)
- return;
+ goto out;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
if (client && client->mode & SILC_UMODE_DETACHED) {
SILC_LOG_DEBUG(("Client is detached, discarding packet"));
- return;
+ goto out;
}
/* Send SILC_NOTIFY_TYPE_ERROR to indicate that such destination ID
packet->dst_id_len,
packet->dst_id_type);
if (!idp)
- return;
+ goto out;
error = SILC_STATUS_ERR_NO_SUCH_CLIENT_ID;
if (packet->src_id_type == SILC_ID_CLIENT) {
}
silc_buffer_free(idp);
- return;
+ goto out;
}
/* Check whether destination client wishes to receive private messages */
if (client && !(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY) &&
client->mode & SILC_UMODE_BLOCK_PRIVMSG) {
SILC_LOG_DEBUG(("Client blocks private messages, discarding packet"));
- return;
+ goto out;
}
/* Send the private message */
silc_server_packet_route(server, dst_sock, packet);
+
+ out:
+ silc_packet_free(packet);
}
/* Received private message key packet.. This packet is never for us. It is to
SILC_LOG_DEBUG(("Start"));
if (packet->src_id_type != SILC_ID_CLIENT ||
- packet->dst_id_type != SILC_ID_CLIENT)
- return;
-
- if (!packet->dst_id)
+ packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) {
+ silc_packet_free(packet);
return;
+ }
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
packet->dst_id_len, NULL,
&idata, NULL);
- if (!dst_sock)
+ if (!dst_sock) {
+ silc_packet_free(packet);
return;
+ }
/* Relay the packet */
silc_server_packet_route(server, dst_sock, packet);
+
+ silc_packet_free(packet);
}
/* Processes incoming command reply packet. The command reply packet may
SILC_LOG_DEBUG(("Start"));
- if (packet->dst_id_type == SILC_ID_CHANNEL)
+ if (packet->dst_id_type == SILC_ID_CHANNEL) {
+ silc_packet_free(packet);
return;
+ }
if (packet->dst_id_type == SILC_ID_CLIENT) {
/* Destination must be one of ours */
if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT,
- &id, sizeof(id)))
+ &id, sizeof(id))) {
+ silc_packet_free(packet);
return;
+ }
client = silc_idlist_find_client_by_id(server->local_list, &id,
TRUE, NULL);
if (!client) {
SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
+ silc_packet_free(packet);
return;
}
}
/* For now this must be for us */
if (memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
SILC_LOG_ERROR(("Cannot process command reply to unknown server"));
+ silc_packet_free(packet);
return;
}
}
/* Relay the packet to the client */
if (packet->dst_id_type == SILC_ID_CLIENT && client)
silc_server_packet_route(server, client->connection, packet);
+
+ silc_packet_free(packet);
}
/* Process received channel message. The message can be originated from
/* Sanity checks */
if (packet->dst_id_type != SILC_ID_CHANNEL) {
SILC_LOG_DEBUG(("Received bad message for channel, dropped"));
- return;
+ goto out;
}
/* Find channel entry */
if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
&id, sizeof(id)))
- return;
+ goto out;
channel = silc_idlist_find_channel_by_id(server->local_list, &id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list, &id, NULL);
packet->dst_id_len,
packet->dst_id_type);
if (!idp)
- return;
+ goto out;
error = SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID;
if (packet->src_id_type == SILC_ID_CLIENT) {
}
silc_buffer_free(idp);
- return;
+ goto out;
}
}
not client (as it can be server as well) we don't do the check. */
if (!silc_id_str2id2(packet->src_id, packet->src_id_len,
packet->src_id_type, &sid))
- return;
+ goto out;
if (sid.type == SILC_ID_CLIENT) {
sender_entry = silc_idlist_find_client_by_id(server->local_list,
SILC_ID_GET_ID(sid),
if (!sender_entry || !silc_server_client_on_channel(sender_entry,
channel, &chl)) {
SILC_LOG_DEBUG(("Client not on channel"));
- return;
+ goto out;
}
/* If channel is moderated check that client is allowed to send
!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Channel is silenced from normal users"));
- return;
+ goto out;
}
if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS &&
chl->mode & SILC_CHANNEL_UMODE_CHANOP &&
!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
SILC_LOG_DEBUG(("Channel is silenced from operators"));
- return;
+ goto out;
}
if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
SILC_LOG_DEBUG(("Sender is quieted on the channel"));
- return;
+ goto out;
}
/* If the packet is coming from router, but the client entry is local
if (server->server_type == SILC_ROUTER &&
idata->conn_type == SILC_CONN_ROUTER && local) {
SILC_LOG_DEBUG(("Channel message rerouted to the sender, drop it"));
- return;
+ goto out;
}
}
packet->src_id_type, sender_entry,
packet->buffer.data,
silc_buffer_len(&packet->buffer));
+
+ out:
+ silc_packet_free(packet);
}
/* Received channel key packet. We distribute the key to all of our locally
if (packet->src_id_type != SILC_ID_SERVER ||
(server->server_type == SILC_ROUTER && !server->backup_router &&
- idata->conn_type == SILC_CONN_ROUTER))
+ idata->conn_type == SILC_CONN_ROUTER)) {
+ silc_packet_free(packet);
return;
+ }
/* Save the channel key */
channel = silc_server_save_channel_key(server, buffer, NULL);
if (!channel) {
SILC_LOG_ERROR(("Bad channel key from %s", idata->sconn->remote_host));
+ silc_packet_free(packet);
return;
}
we will also send it to locally connected servers. */
silc_server_send_channel_key(server, sock, channel, FALSE);
- if (server->server_type != SILC_BACKUP_ROUTER) {
+ if (server->server_type != SILC_BACKUP_ROUTER)
/* Distribute to local cell backup routers. */
silc_server_backup_send(server, (SilcServerEntry)idata,
SILC_PACKET_CHANNEL_KEY, 0,
buffer->data, silc_buffer_len(buffer),
FALSE, TRUE);
- }
+
+ silc_packet_free(packet);
}
/* Received New Client packet and processes it. Creates Client ID for the
SilcClientEntry client;
SilcClientID *client_id;
char *username = NULL, *realname = NULL;
- SilcUInt16 username_len;
+ SilcUInt16 username_len, nickname_len;
SilcUInt32 id_len, tmp_len;
int ret;
- char *host, *nickname, *nicknamec;
+ char *host, *nickname = NULL, *nicknamec;
const char *hostname, *ip;
SILC_LOG_DEBUG(("Creating new client"));
- if (idata->conn_type != SILC_CONN_CLIENT)
+ if (idata->conn_type != SILC_CONN_CLIENT) {
+ silc_packet_free(packet);
return NULL;
+ }
/* Take client entry */
client = (SilcClientEntry)idata;
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
- /* Remove the old cache entry. */
- if (!silc_idcache_del_by_context(server->local_list->clients, client,
- NULL)) {
- SILC_LOG_INFO(("Unauthenticated client attempted to register to network"));
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_NOT_AUTHENTICATED, NULL);
- silc_server_free_sock_user_data(server, sock, NULL);
- return NULL;
- }
+ SILC_LOG_DEBUG(("%s %s", ip, hostname));
/* Make sure this client hasn't registered already */
if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
- silc_server_disconnect_remote(server, sock,
- SILC_STATUS_ERR_OPERATION_ALLOWED,
- "Too many registrations");
- silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
/* Parse incoming packet */
ret = silc_buffer_unformat(buffer,
+ SILC_STR_ADVANCE,
SILC_STR_UI16_NSTRING_ALLOC(&username,
&username_len),
SILC_STR_UI16_STRING_ALLOC(&realname),
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
if (username_len > 128) {
- username[128] = '\0';
username_len = 128;
+ username[username_len - 1] = '\0';
}
/* Check for valid username string */
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
- /* Nickname is initially same as username */
- nickname = strdup(username);
+ /* Take nickname from NEW_CLIENT packet, if present */
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI16_NSTRING_ALLOC(&nickname,
+ &nickname_len),
+ SILC_STR_END)) {
+ if (nickname_len > 128) {
+ nickname_len = 128;
+ nickname[nickname_len - 1] = '\0';
+ }
+ }
+
+ /* Nickname is initially same as username, if not present in NEW_CLIENT */
+ if (!nickname)
+ nickname = strdup(username);
/* Make sanity checks for the hostname of the client. If the hostname
is provided in the `username' check that it is the same than the
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
NULL);
silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
username = newusername;
}
+ SILC_LOG_DEBUG(("%s %s", ip, hostname));
+
/* Create Client ID */
if (!silc_id_create_client_id(server, server->id, server->rng,
server->md5hash, nicknamec,
silc_server_disconnect_remote(server, sock,
SILC_STATUS_ERR_BAD_NICKNAME, NULL);
silc_server_free_sock_user_data(server, sock, NULL);
+ silc_packet_free(packet);
return NULL;
}
client->userinfo = realname ? realname : strdup(username);
client->id = client_id;
id_len = silc_id_get_len(client_id, SILC_ID_CLIENT);
-
- /* Add the client again to the ID cache */
- silc_idcache_add(server->local_list->clients, nicknamec,
- client_id, client);
+ silc_idcache_update_by_context(server->local_list->clients, client,
+ client_id, nicknamec, TRUE);
/* Notify our router about new client on the SILC network */
silc_server_send_new_id(server, SILC_PRIMARY_ROUTE(server),
if (server->server_type == SILC_ROUTER)
silc_server_check_watcher_list(server, client, NULL, 0);
+ silc_packet_free(packet);
return client;
}
SILC_LOG_DEBUG(("Creating new server"));
if (idata->conn_type != SILC_CONN_SERVER &&
- idata->conn_type != SILC_CONN_ROUTER)
+ idata->conn_type != SILC_CONN_ROUTER) {
+ silc_packet_free(packet);
return NULL;
+ }
/* Take server entry */
new_server = (SilcServerEntry)idata;
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
/* Statistics */
if (server->server_type == SILC_ROUTER)
id_type = silc_id_payload_get_type(idp);
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
/* Normal server cannot have other normal server connections */
server_entry = (SilcServerEntry)idata;
SilcPacket packet)
{
silc_server_new_id_real(server, sock, packet, &packet->buffer, TRUE);
+ silc_packet_free(packet);
}
/* Receoved New Id List packet, list of New ID payloads inside one
SILC_LOG_DEBUG(("Processing New ID List"));
if (idata->conn_type == SILC_CONN_CLIENT ||
- packet->src_id_type != SILC_ID_SERVER)
+ packet->src_id_type != SILC_ID_SERVER) {
+ silc_packet_free(packet);
return;
+ }
/* If the sender of this packet is server and we are router we need to
broadcast this packet to other routers in the network. Broadcast
}
idp = silc_buffer_alloc(256);
- if (!idp)
+ if (!idp) {
+ silc_packet_free(packet);
return;
+ }
while (silc_buffer_len(&packet->buffer)) {
SILC_GET16_MSB(id_len, packet->buffer.data + 2);
}
silc_buffer_free(idp);
+ silc_packet_free(packet);
}
/* Received New Channel packet. Information about new channels in the
SilcPacket packet)
{
silc_server_new_channel_process(server, sock, packet, &packet->buffer);
+ silc_packet_free(packet);
}
/* Received New Channel List packet, list of New Channel List payloads inside
if (idata->conn_type == SILC_CONN_CLIENT ||
packet->src_id_type != SILC_ID_SERVER ||
- server->server_type == SILC_SERVER)
+ server->server_type == SILC_SERVER) {
+ silc_packet_free(packet);
return;
+ }
buffer = silc_buffer_alloc(512);
- if (!buffer)
+ if (!buffer) {
+ silc_packet_free(packet);
return;
+ }
while (silc_buffer_len(&packet->buffer)) {
SILC_GET16_MSB(len1, packet->buffer.data);
}
silc_buffer_free(buffer);
+ silc_packet_free(packet);
}
/* Received key agreement packet. This packet is never for us. It is to
SILC_LOG_DEBUG(("Start"));
if (packet->src_id_type != SILC_ID_CLIENT ||
- packet->dst_id_type != SILC_ID_CLIENT)
- return;
-
- if (!packet->dst_id)
+ packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) {
+ silc_packet_free(packet);
return;
+ }
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
packet->dst_id_len, NULL,
&idata, NULL);
- if (!dst_sock)
+ if (!dst_sock) {
+ silc_packet_free(packet);
return;
+ }
/* Relay the packet */
silc_server_packet_route(server, dst_sock, packet);
+ silc_packet_free(packet);
}
/* Received connection auth request packet that is used during connection
if (packet->src_id_type && packet->src_id_type != SILC_ID_CLIENT) {
SILC_LOG_DEBUG(("Request not from client"));
+ silc_packet_free(packet);
return;
}
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
/* Parse the payload */
ret = silc_buffer_unformat(&packet->buffer,
SILC_STR_UI_SHORT(&conn_type),
SILC_STR_UI_SHORT(NULL),
SILC_STR_END);
- if (ret == -1)
- return;
-
- if (conn_type != SILC_CONN_CLIENT)
+ if (ret == -1 || conn_type != SILC_CONN_CLIENT) {
+ silc_packet_free(packet);
return;
+ }
/* Get the authentication method for the client */
auth_meth = SILC_AUTH_NONE;
/* Send it back to the client */
silc_server_send_connection_auth_request(server, sock, conn_type, auth_meth);
+ silc_packet_free(packet);
}
/* Received file transger packet. This packet is never for us. It is to
SILC_LOG_DEBUG(("Start"));
if (packet->src_id_type != SILC_ID_CLIENT ||
- packet->dst_id_type != SILC_ID_CLIENT)
- return;
-
- if (!packet->dst_id)
+ packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) {
+ silc_packet_free(packet);
return;
+ }
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
packet->dst_id_len, NULL,
&idata, NULL);
- if (!dst_sock)
+ if (!dst_sock) {
+ silc_packet_free(packet);
return;
+ }
/* Relay the packet */
silc_server_packet_route(server, dst_sock, packet);
+ silc_packet_free(packet);
}
typedef struct {
SILC_LOG_DEBUG(("Start"));
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
if (!reply || !silc_command_get_status(reply->payload, NULL, NULL)) {
SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
SilcServerResumeResolve r;
const char *cipher, *hostname, *ip;
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
if (silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING(&id_string, &id_len),
static void silc_server_packet_parse_type(SilcServer server,
SilcPacketStream sock,
SilcPacket packet);
+static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet);
/************************ Static utility functions **************************/
!(idata->status & SILC_IDLIST_STATUS_REGISTERED)) &&
packet->type != SILC_PACKET_NEW_CLIENT &&
packet->type != SILC_PACKET_NEW_SERVER &&
+ packet->type != SILC_PACKET_CONNECTION_AUTH_REQUEST &&
packet->type != SILC_PACKET_DISCONNECT)
return FALSE;
*/
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
- /* XXX handle rekey */
+ silc_server_rekey(server, sock, packet);
break;
case SILC_PACKET_FTP:
server->repository = silc_skr_alloc();
if (!server->repository)
return FALSE;
+ server->conns = silc_dlist_init();
+ if (!server->conns)
+ return FALSE;
*new_server = server;
SilcBool silc_server_init_secondary(SilcServer server)
{
+ return TRUE;
#if 0
int sock = 0;
SilcPacketStream newsocket = NULL;
silc_dlist_add(server->listeners, listener);
-#if 0
- /* Perform name and address lookups to resolve the listenning address
- and port. */
- if (!silc_net_check_local_by_sock(sock, &newsocket->hostname,
- &newsocket->ip)) {
- if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
- !newsocket->ip) {
- SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
- newsocket->hostname ? newsocket->hostname :
- newsocket->ip ? newsocket->ip : ""));
- server->stat.conn_failures++;
- goto err;
- }
- if (!newsocket->hostname)
- newsocket->hostname = strdup(newsocket->ip);
- }
- newsocket->port = silc_net_get_local_port(sock);
-#endif
-
/* Create a Server ID for the server. */
port = silc_net_listener_get_port(listener, NULL);
ip = silc_net_listener_get_ip(listener, NULL);
silc_idlist_add_server(server->local_list, strdup(server->server_name),
server->server_type, server->id, NULL, NULL);
if (!id_entry) {
- SILC_LOG_ERROR(("Could not add ourselves to cache"));
+ SILC_LOG_ERROR(("Could not add local server to cache"));
goto err;
}
id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
silc_server_free_sock_user_data(server, ps,
"Server is shutting down");
}
+ silc_dlist_uninit(list);
}
/* We are not connected to network anymore */
server->stat.conn_num++;
/* Set source ID to packet stream */
- if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, &server->id,
+ if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, server->id,
0, NULL)) {
silc_packet_stream_destroy(sconn->sock);
silc_server_connection_free(sconn);
{
SilcPacketStream sock = context;
SilcUnknownEntry entry = silc_packet_get_context(sock);
+ SilcIDListData idata = (SilcIDListData)entry;
SilcServer server = entry->server;
SilcServerConfigConnParams *param;
+ SilcServerConnection sconn;
void *id_entry;
+ const char *hostname;
+ SilcUInt16 port;
+
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, NULL, &port);
if (success == FALSE) {
/* Authentication failed */
client->mode |= SILC_UMODE_ANONYMOUS;
}
- /* Add public key to hash list (for whois using attributes) */
- if (!silc_hash_table_find_by_context(server->pk_hash,
- entry->data.public_key,
- client, NULL))
- silc_hash_table_add(server->pk_hash,
- entry->data.public_key, client);
+ /* Add public key to repository */
+ if (!silc_server_get_public_key_by_client(server, client, NULL))
+ silc_skr_add_public_key_simple(server->repository,
+ entry->data.public_key,
+ SILC_SKR_USAGE_IDENTIFICATION, client);
id_entry = (void *)client;
break;
break;
}
+ /* Add connection to server->conns so that we know we have connection
+ to this peer. */
+ sconn = silc_calloc(1, sizeof(*sconn));
+ sconn->server = server;
+ sconn->sock = sock;
+ sconn->remote_host = strdup(hostname);
+ sconn->remote_port = port;
+ silc_dlist_add(server->conns, sconn);
+ idata->sconn = sconn;
+
/* Add the common data structure to the ID entry. */
silc_idlist_add_data(id_entry, (SilcIDListData)entry);
silc_packet_set_context(sock, id_entry);
/* Connection has been fully established now. Everything is ok. */
SILC_LOG_DEBUG(("New connection authenticated"));
- /* XXX Add connection to server->conns so that we know we have connection
- to this peer. */
- /* XXX */
#if 0
/* Perform keepalive. */
{
SilcPacketStream sock = context;
SilcUnknownEntry entry = silc_packet_get_context(sock);
+ SilcIDListData idata = (SilcIDListData)entry;
SilcServer server = entry->server;
SilcConnAuth connauth;
SilcCipher send_key, receive_key;
silc_packet_set_keys(sock, send_key, receive_key, hmac_send,
hmac_receive, FALSE);
+ idata->rekey = rekey;
+ idata->public_key = silc_pkcs_public_key_copy(prop->public_key);
+
SILC_LOG_DEBUG(("Starting connection authentication"));
server->stat.auth_attempts++;
server->stat.conn_num++;
/* Set source ID to packet stream */
- if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, &server->id,
+ if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, server->id,
0, NULL)) {
/* Out of memory */
server->stat.conn_failures++;
idata->sconn->op = silc_ske_rekey_initiator(ske, sock, idata->rekey);
}
+/* Responder rekey completion callback */
+
+static void
+silc_server_rekey_resp_completion(SilcSKE ske,
+ SilcSKEStatus status,
+ const SilcSKESecurityProperties prop,
+ const SilcSKEKeyMaterial keymat,
+ SilcSKERekeyMaterial rekey,
+ void *context)
+{
+ SilcPacketStream sock = context;
+ SilcIDListData idata = silc_packet_get_context(sock);
+
+ idata->sconn->op = NULL;
+ if (status != SILC_SKE_STATUS_OK) {
+ SILC_LOG_ERROR(("Error during rekey protocol with %s",
+ idata->sconn->remote_host));
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Rekey protocol completed with %s:%d [%s]",
+ idata->sconn->remote_host, idata->sconn->remote_port,
+ SILC_CONNTYPE_STRING(idata->conn_type)));
+
+ /* Save rekey data for next rekey */
+ idata->rekey = rekey;
+}
+
+/* Start rekey as responder */
+
+static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
+ SilcPacket packet)
+{
+ SilcIDListData idata = silc_packet_get_context(sock);
+ SilcSKE ske;
+
+ SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]",
+ idata->sconn->remote_host, idata->sconn->remote_port,
+ SILC_CONNTYPE_STRING(idata->conn_type)));
+
+ /* Allocate SKE */
+ ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
+ server->public_key, server->private_key, sock);
+ if (!ske) {
+ silc_packet_free(packet);
+ return;
+ }
+
+ /* Set SKE callbacks */
+ silc_ske_set_callbacks(ske, NULL, silc_server_rekey_resp_completion, sock);
+
+ /* Perform rekey */
+ idata->sconn->op = silc_ske_rekey_responder(ske, sock, idata->rekey,
+ packet);
+}
+
/****************************** Disconnection *******************************/
memset(tmp, 0, sizeof(tmp));
// silc_socket_get_error(sock, tmp, sizeof(tmp));
- silc_socket_stream_get_info(sock, NULL, &hostname, NULL, &port);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, NULL, &port);
SILC_LOG_INFO(("Closing connection %s:%d [%s] %s", hostname, port,
SILC_CONNTYPE_STRING(idata->conn_type),
tmp[0] ? tmp : ""));
/* Decode destination Client ID */
if (!client_id) {
- if (!silc_id_str2id(id_data, id_len, SILC_ID_CHANNEL, &clid, sizeof(clid)))
+ if (!silc_id_str2id(id_data, id_len, SILC_ID_CLIENT, &clid, sizeof(clid)))
return NULL;
id = silc_id_dup(&clid, SILC_ID_CLIENT);
} else {
if (!strchr(entry->username, '@') && entry->connection) {
hsock = entry->connection;
silc_strncat(uh, sizeof(uh), "@", 1);
- silc_socket_stream_get_info(hsock, NULL, (const char **)&tmp,
- NULL, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(hsock),
+ NULL, (const char **)&tmp, NULL, NULL);
silc_strncat(uh, sizeof(uh), tmp, strlen(tmp));
}
if (!strchr(entry->username, '@') && entry->connection) {
hsock = entry->connection;
silc_strncat(uh, sizeof(uh), "@", 1);
- silc_socket_stream_get_info(hsock, NULL, (const char **)&tmp,
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(hsock),
+ NULL, (const char **)&tmp,
NULL, NULL);
silc_strncat(uh, sizeof(uh), tmp, strlen(tmp));
}
while ((conn = silc_dlist_get(server->conns))) {
if (!conn->sock)
continue;
- silc_socket_stream_get_info(conn->sock, NULL, NULL, &ipaddr, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
+ NULL, NULL, &ipaddr, NULL);
idata = silc_packet_get_context(conn->sock);
if (!strcmp(ipaddr, ip) && idata && idata->conn_type == type)
count++;
if (!conn->sock)
continue;
idata = silc_packet_get_context(conn->sock);
- silc_socket_stream_get_info(conn->sock, NULL, NULL, &ipaddr, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->sock),
+ NULL, NULL, &ipaddr, NULL);
if (!strcmp(ipaddr, ip) &&
(!port || conn->remote_port == port) &&
idata->conn_type == type)
return public_key;
}
+/* Find public key by client for identification purposes. Finds keys
+ with SILC_SKR_USAGE_IDENTIFICATION. */
+
+SilcBool silc_server_get_public_key_by_client(SilcServer server,
+ SilcClientEntry client,
+ SilcPublicKey *public_key)
+{
+ SilcPublicKey pubkey = NULL;
+ SilcBool ret = FALSE;
+
+ pubkey = silc_server_get_public_key(server, SILC_SKR_USAGE_IDENTIFICATION,
+ client);
+ if (pubkey)
+ ret = TRUE;
+
+ if (public_key)
+ *public_key = pubkey;
+
+ return ret;
+}
+
/* Check whether the connection `sock' is allowed to connect to us. This
checks for example whether there is too much connections for this host,
and required version for the host etc. */
char *r_vendor_version = NULL, *l_vendor_version;
const char *hostname, *ip;
- silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL);
+ silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+ NULL, &hostname, &ip, NULL);
SILC_LOG_DEBUG(("Checking whether connection is allowed"));
users are removed from the channel. Returns TRUE if the channel is
destroyed totally, and FALSE if it is permanent and remains. */
SilcBool silc_server_channel_delete(SilcServer server,
- SilcChannelEntry channel);
+ SilcChannelEntry channel);
/* Returns TRUE if the given client is on the channel. FALSE if not.
This works because we assure that the user list on the channel is
always in up to date thus we can only check the channel list from
`client' which is faster than checking the user list from `channel'. */
SilcBool silc_server_client_on_channel(SilcClientEntry client,
- SilcChannelEntry channel,
- SilcChannelClientEntry *chl);
+ SilcChannelEntry channel,
+ SilcChannelClientEntry *chl);
/* Find number of sockets by IP address indicated by `ip'. Returns 0 if
socket connections with the IP address does not exist. */
SilcSKRKeyUsage usage,
void *key_context);
+/* Find public key by client for identification purposes. Finds keys
+ with SILC_SKR_USAGE_IDENTIFICATION. */
+SilcBool silc_server_get_public_key_by_client(SilcServer server,
+ SilcClientEntry client,
+ SilcPublicKey *public_key);
+
/* Check whether the connection `sock' is allowed to connect to us. This
checks for example whether there is too much connections for this host,
and required version for the host etc. */
/* Checks that client has rights to add or remove channel modes. If any
of the checks fails FALSE is returned. */
SilcBool silc_server_check_cmode_rights(SilcServer server,
- SilcChannelEntry channel,
- SilcChannelClientEntry client,
- SilcUInt32 mode);
+ SilcChannelEntry channel,
+ SilcChannelClientEntry client,
+ SilcUInt32 mode);
/* Check that the client has rights to change its user mode. Returns
FALSE if setting some mode is not allowed. */
silc_skr_find_set_usage(find, usage);
silc_skr_find_set_context(find, key_context ? key_context : (void *)usage);
silc_skr_find(skr, NULL, find, my_find_callback, &status);
- if (status != SILC_SKR_OK) {
+ if (status == SILC_SKR_ALREADY_EXIST) {
silc_pkcs_public_key_free(public_key);
SILC_SERVER_LOG_WARNING(("Warning: public key file \"%s\" already "
"configured, ignoring this key", p));
silc_free(si->group);
silc_free(si->motd_file);
silc_free(si->pid_file);
- silc_pkcs_public_key_free(si->public_key);
- silc_pkcs_private_key_free(si->private_key);
+ if (si->public_key)
+ silc_pkcs_public_key_free(si->public_key);
+ if (si->private_key)
+ silc_pkcs_private_key_free(si->private_key);
silc_free(si);
}
SilcBool silc_server_config_register_pkcs(SilcServer server)
{
- return TRUE;
+ return FALSE;
}
/* Sets log files where log messages are saved by the server logger. */
/* Unregister the default crypto stuff so that configuration takes effect */
silc_cipher_unregister_all();
- silc_pkcs_unregister_all();
+ /* silc_pkcs_unregister_all(); MUST NOT do this anymore; SilcPublicKey
+ parsed from config file references pointers so we cannot unregister */
silc_hash_unregister_all();
silc_hmac_unregister_all();