command.c \
command_reply.c \
server_util.c \
- server_backup.c
+ server_backup.c \
+ server_http.c
LIBS = $(SILC_COMMON_LIBS)
LDADD =
SILC_STR_END);
silc_hash_table_list(channel->ban_list, &htl);
while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
- list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
- type);
+ list = silc_argument_payload_encode_one(list, tmp2->data,
+ silc_buffer_len(tmp2), type);
silc_hash_table_list_reset(&htl);
}
+ tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+
/* Send BAN notify type to local servers (but not clients) and to
network. */
if (atype && tmp && len2) {
if (server->server_type == SILC_ROUTER)
silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
SILC_NOTIFY_TYPE_BAN, 3,
- id, id_len,
+ tmp_id, id_len,
atype, 1,
tmp ? blist.data : NULL,
tmp ? silc_buffer_len(&blist) : 0);
/* Send the reply back to the client */
silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
SILC_STATUS_OK, 0, ident, 2,
- 2, id, id_len,
+ 2, tmp_id, id_len,
3, list ? list->data : NULL,
list ? silc_buffer_len(list) : 0);
silc_buffer_free(list);
if (!client)
return;
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
-
silc_server_remove_from_channels(server, NULL, client, TRUE,
NULL, TRUE, FALSE);
silc_idlist_del_data(client);
SILC_LOG_DEBUG(("Saved client public key from attributes"));
- /* Add to public key hash table */
- if (!silc_hash_table_find_by_context(server->pk_hash,
- client->data.public_key,
- client, NULL))
- silc_hash_table_add(server->pk_hash,
- client->data.public_key, client);
+ /* Add client's public key to repository */
+ if (!silc_server_get_public_key_by_client(server, client, NULL))
+ silc_skr_add_public_key_simple(server->repository,
+ client->data.public_key,
+ SILC_SKR_USAGE_IDENTIFICATION,
+ client, NULL);
silc_free(pk.type);
silc_free(pk.data);
client);
}
+ /* If client is global and is not on any channel then add that we'll
+ expire the entry after a while. */
+ if (global) {
+ silc_idlist_find_client_by_id(server->global_list, client->id,
+ FALSE, &cache);
+ if (!silc_hash_table_count(client->channels))
+ silc_dlist_add(server->expired_clients, client);
+ }
+
return TRUE;
}
}
if (!client->data.public_key) {
- if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
- client, NULL))
- silc_hash_table_add(server->pk_hash, public_key, client);
-
+ /* Add client's public key to repository */
+ if (!silc_server_get_public_key_by_client(server, client, NULL))
+ silc_skr_add_public_key_simple(server->repository,
+ public_key,
+ SILC_SKR_USAGE_IDENTIFICATION,
+ client, NULL);
client->data.public_key = public_key;
public_key = NULL;
}
SilcServerEntry
silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
- SilcBool registered, SilcIDCacheEntry *ret_entry)
+ SilcBool registered,
+ SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server;
return FALSE;
}
+/* ID Cache destructor */
+
+void silc_idlist_server_destructor(SilcIDCache cache,
+ SilcIDCacheEntry entry,
+ void *dest_context,
+ void *app_context)
+{
+ silc_free(entry->name);
+}
+
/******************************************************************************
Client entry functions
void *dest_context,
void *app_context)
{
- SilcServer server = app_context;
+ SilcServer server = dest_context;
SilcClientEntry client;
client = (SilcClientEntry)entry->context;
if (client) {
- /* Remove this client from the public key hash list */
+ /* Remove client's public key from repository, this will free it too. */
if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key, client);
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
assert(!silc_hash_table_count(client->channels));
silc_free(client->nickname);
silc_free(client->userinfo);
silc_free(client->id);
silc_free(client->attrs);
- if (client->data.public_key)
- silc_pkcs_public_key_free(client->data.public_key);
silc_hash_table_free(client->channels);
memset(client, 'A', sizeof(*client));
NULL, NULL, NULL, TRUE);
if (!silc_idcache_add(id_list->channels, channel_namec,
- (void *)channel->id, (void *)channel /*XXX, expire */)) {
+ (void *)channel->id, (void *)channel)) {
silc_hmac_free(channel->hmac);
silc_hash_table_free(channel->user_list);
silc_free(channel);
return channel;
}
+/* ID Cache destructor */
+
+void silc_idlist_channel_destructor(SilcIDCache cache,
+ SilcIDCacheEntry entry,
+ void *dest_context,
+ void *app_context)
+{
+ silc_free(entry->name);
+}
+
/* Foreach callbcak to free all users from the channel when deleting a
channel entry. */
silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
SilcServerID *new_id);
int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
+void silc_idlist_server_destructor(SilcIDCache cache,
+ SilcIDCacheEntry entry,
+ void *dest_context,
+ void *app_context);
SilcClientEntry
silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
SilcChannelID *id, SilcServerEntry router,
SilcCipher send_key, SilcCipher receive_key,
SilcHmac hmac);
+void silc_idlist_channel_destructor(SilcIDCache cache,
+ SilcIDCacheEntry entry,
+ void *dest_context,
+ void *app_context);
int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry);
SilcChannelEntry
silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
silc_schedule_task_del_by_context(server->schedule, client);
- /* Remove from public key hash table. */
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash, client->data.public_key,
- client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (client->data.public_key) {
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
+ client->data.public_key = NULL;
+ }
/* Remove the client from all channels. */
silc_server_remove_from_channels(server, NULL, client, TRUE,
client->mode = 0;
client->router = NULL;
client->connection = NULL;
+ silc_dlist_add(server->expired_clients, client);
break;
case SILC_NOTIFY_TYPE_TOPIC_SET:
if (local)
silc_server_del_from_watcher_list(server, client);
- /* Remove from public key hash table. */
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
-
/* Remove the client */
silc_idlist_del_data(client);
silc_idlist_del_client(local ? server->local_list :
silc_server_check_watcher_list(server, client, NULL,
SILC_NOTIFY_TYPE_KILLED);
- /* Remove from public key hash table. */
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (client->data.public_key) {
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
+ client->data.public_key = NULL;
+ }
/* Update statistics */
server->stat.clients--;
client->mode = 0;
client->router = NULL;
client->connection = NULL;
+ silc_dlist_add(server->expired_clients, client);
break;
}
if (!client)
goto out;
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
-
silc_server_remove_from_channels(server, NULL, client, TRUE,
NULL, TRUE, FALSE);
silc_idlist_del_data(client);
SilcChannelID id;
SilcClientID cid;
SilcID sid;
- void *sender_id = NULL;
SilcClientEntry sender_entry = NULL;
SilcIDListData idata;
SilcChannelClientEntry chl;
/* Distribute the packet to our local clients. This will send the
packet for further routing as well, if needed. */
- silc_server_packet_relay_to_channel(server, sock, channel, sender_id,
- packet->src_id_type, sender_entry,
- packet->buffer.data,
+ silc_server_packet_relay_to_channel(server, sock, channel,
+ SILC_ID_GET_ID(sid), sid.type,
+ sender_entry, packet->buffer.data,
silc_buffer_len(&packet->buffer));
out:
username[username_len - 1] = '\0';
}
+ /* 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);
+ nickname_len = strlen(nickname);
+ }
+
/* Check for valid username string */
- nicknamec = silc_identifier_check(username, username_len,
+ nicknamec = silc_identifier_check(nickname, nickname_len,
SILC_STRING_UTF8, 128, &tmp_len);
if (!nicknamec) {
silc_free(username);
silc_free(realname);
+ silc_free(nickname);
SILC_LOG_ERROR(("Client %s (%s) sent bad username string '%s', closing "
"connection", hostname, ip, username));
silc_server_disconnect_remote(server, sock,
return NULL;
}
- /* 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
resolved hostname, or if not resolved the hostname that appears in
host = silc_memdup(username + tlen + 1, strlen(username) - tlen - 1);
if (strcmp(hostname, ip) && strcmp(hostname, host)) {
+ silc_free(nickname);
silc_free(username);
silc_free(host);
silc_free(realname);
client->data.public_key);
phostname = strdup(silc_pubkey->identifier.host);
if (!strcmp(hostname, ip) && phostname && strcmp(phostname, host)) {
+ silc_free(nickname);
silc_free(username);
silc_free(host);
silc_free(phostname);
silc_server_check_watcher_list(server, entry, NULL, 0);
if (server->server_type == SILC_ROUTER) {
- /* Add the client's public key to hash table or get the key with
+ /* Add the client's public key to repository or get the key with
GETKEY command. */
if (entry->data.public_key) {
- if (!silc_hash_table_find_by_context(server->pk_hash,
- entry->data.public_key,
- entry, NULL))
- silc_hash_table_add(server->pk_hash, entry->data.public_key,
- entry);
- } else
+ if (!silc_server_get_public_key_by_client(server, entry, NULL))
+ silc_skr_add_public_key_simple(server->repository,
+ entry->data.public_key,
+ SILC_SKR_USAGE_IDENTIFICATION,
+ entry, NULL);
+ } else {
silc_server_send_command(server, router_sock,
SILC_COMMAND_GETKEY, ++server->cmd_ident,
1, 1, buffer->data,
silc_buffer_len(buffer));
+ }
}
}
break;
SilcHashTableList htl;
SilcChannelClientEntry chl;
SilcServerResumeResolve r;
+ SilcPublicKey public_key;
const char *cipher, *hostname, *ip;
silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
silc_packet_set_context(sock, detached_client);
detached_client->connection = sock;
- if (detached_client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- detached_client->data.public_key,
- detached_client);
- if (idata->public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- idata->public_key, idata);
+ if (detached_client->data.public_key) {
+ /* Delete the detached client's public key from repository */
+ silc_skr_del_public_key(server->repository,
+ detached_client->data.public_key,
+ detached_client);
+ detached_client->data.public_key = NULL;
+ }
+
+ if (idata->public_key) {
+ /* Delete the resuming client's public key from repository. It will
+ be added later again. */
+ public_key = silc_pkcs_public_key_copy(idata->public_key);
+ silc_skr_del_public_key(server->repository, idata->public_key, idata);
+ idata->public_key = public_key;
+ }
/* Take new keys and stuff into use in the old entry */
silc_idlist_del_data(detached_client);
silc_idlist_add_data(detached_client, idata);
- if (detached_client->data.public_key)
- silc_hash_table_add(server->pk_hash,
- detached_client->data.public_key, detached_client);
+ if (detached_client->data.public_key) {
+ /* Add the resumed client's public key back to repository. */
+ if (!silc_server_get_public_key_by_client(server, detached_client, NULL))
+ silc_skr_add_public_key_simple(server->repository,
+ detached_client->data.public_key,
+ SILC_SKR_USAGE_IDENTIFICATION,
+ detached_client, NULL);
+ }
detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
/* Client is detached, and now it is resumed. Remove the detached
mode and mark that it is resumed. */
- if (detached_client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- detached_client->data.public_key,
- detached_client);
+ if (detached_client->data.public_key) {
+ /* Delete the detached client's public key from repository */
+ silc_skr_del_public_key(server->repository,
+ detached_client->data.public_key,
+ detached_client);
+ detached_client->data.public_key = NULL;
+ }
silc_idlist_del_data(detached_client);
detached_client->mode &= ~SILC_UMODE_DETACHED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
+ silc_dlist_del(server->expired_clients, detached_client);
/* Check if anyone is watching this client */
if (server->server_type == SILC_ROUTER)
#include "serverincludes.h"
#include "server_internal.h"
-/************************* Types and definitions ***************************/
+/************************* Types and definitions ****************************/
SILC_TASK_CALLBACK(silc_server_get_stats);
SILC_TASK_CALLBACK(silc_server_connect_router);
SILC_TASK_CALLBACK(silc_server_do_rekey);
+SILC_TASK_CALLBACK(silc_server_purge_expired_clients);
static void silc_server_accept_new_connection(SilcNetStatus status,
SilcStream stream,
void *context);
(idata->status & SILC_IDLIST_STATUS_REGISTERED))
return FALSE;
+ /* Ignore packets from disabled connection */
+ if (idata->status & SILC_IDLIST_STATUS_DISABLED &&
+ packet->type != SILC_PACKET_HEARTBEAT &&
+ packet->type != SILC_PACKET_RESUME_ROUTER &&
+ packet->type != SILC_PACKET_REKEY)
+ return FALSE;
+
+ /* Check that the the current client ID is same as in the client's packet. */
+ if (idata->conn_type == SILC_CONN_CLIENT) {
+ SilcClientEntry client = (SilcClientEntry)silc_packet_get_context(stream);
+ SilcClientID client_id;
+
+ if (client->id && packet->src_id &&
+ silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type, &client_id, sizeof(client_id))) {
+ if (!SILC_ID_CLIENT_COMPARE(client->id, &client_id)) {
+ SILC_LOG_DEBUG(("Packet source is not same as sender"));
+ return FALSE;
+ }
+ }
+ }
+
+ if (server->server_type == SILC_ROUTER) {
+ /* Route the packet if it is not destined to us. Other ID types but
+ server are handled separately after processing them. */
+ if (packet->dst_id &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+ packet->dst_id_type == SILC_ID_SERVER &&
+ idata->conn_type != SILC_CONN_CLIENT &&
+ memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
+ SilcPacketStream conn;
+ SilcServerID server_id;
+
+ silc_id_str2id(packet->dst_id, packet->dst_id_len, packet->dst_id_type,
+ &server_id, sizeof(server_id));
+
+ conn = silc_server_route_get(server, &server_id, SILC_ID_SERVER);
+ if (!conn) {
+ SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
+ silc_id_render(&server_id, SILC_ID_SERVER)));
+ return FALSE;
+ }
+
+ silc_server_packet_route(server, conn, packet);
+ silc_packet_free(packet);
+ return TRUE;
+ }
+ }
+
+ /* Broadcast packet if it is marked as broadcast packet and it is
+ originated from router and we are router. */
+ if (server->server_type == SILC_ROUTER &&
+ idata->conn_type == SILC_CONN_ROUTER &&
+ packet->flags & SILC_PACKET_FLAG_BROADCAST) {
+ /* Broadcast to our primary route */
+ silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
+
+ /* If we have backup routers then we need to feed all broadcast
+ data to those servers. */
+ silc_server_backup_broadcast(server, stream, packet);
+ }
+
/* Process packet */
silc_server_packet_parse_type(server, stream, packet);
void *callback_context,
void *stream_context)
{
+ SilcServer server = callback_context;
+ SilcIDListData idata = silc_packet_get_context(stream);
+
SILC_LOG_DEBUG(("End of stream received"));
+
+ if (!idata)
+ return;
+
+ if (server->router_conn && server->router_conn->sock == stream &&
+ !server->router && server->standalone) {
+ silc_server_create_connections(server);
+ } else {
+ /* If backup disconnected then mark that resuming will not be allowed */
+ if (server->server_type == SILC_ROUTER && !server->backup_router &&
+ idata->conn_type == SILC_CONN_SERVER) {
+ SilcServerEntry server_entry = (SilcServerEntry)idata;
+ if (server_entry->server_type == SILC_BACKUP_ROUTER)
+ server->backup_closed = TRUE;
+ }
+
+ silc_server_free_sock_user_data(server, stream, NULL);
+ }
+
+ silc_server_close_connection(server, stream);
}
/* Packet engine callback to indicate error */
void *callback_context,
void *stream_context)
{
+ SilcIDListData idata = silc_packet_get_context(stream);
+ SilcStream sock = silc_packet_stream_get_stream(stream);
+ const char *ip;
+ SilcUInt16 port;
+ if (!idata || !sock)
+ return;
+
+ if (!silc_socket_stream_get_info(sock, NULL, NULL, &ip, &port))
+ return;
+
+ SILC_LOG_ERROR(("Connection %s:%d [%s]: %s",
+ SILC_CONNTYPE_STRING(idata->conn_type), ip, port,
+ silc_packet_error_string(error)));
}
/* Packet stream callbacks */
{
SilcStatus status;
char *message = NULL;
+ const char *hostname, *ip;
if (packet->flags & SILC_PACKET_FLAG_LIST)
break;
message = silc_memdup(packet->buffer.data + 1,
silc_buffer_len(&packet->buffer) - 1);
-#if 0
- SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s",
- sock->ip, sock->hostname,
+ if (!silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL))
+ break;
+
+ SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s", ip, hostname,
silc_get_status_message(status), status,
message ? message : ""));
-#endif
+
silc_free(message);
/* Do not switch to backup in case of error */
server->conns = silc_dlist_init();
if (!server->conns)
return FALSE;
+ server->expired_clients = silc_dlist_init();
+ if (!server->expired_clients)
+ return FALSE;
*new_server = server;
silc_server_backup_free(server);
silc_server_config_unref(&server->config_ref);
- if (server->pk_hash)
- silc_hash_table_free(server->pk_hash);
if (server->rng)
silc_rng_free(server->rng);
if (server->public_key)
silc_idcache_free(server->global_list->channels);
silc_hash_table_free(server->watcher_list);
silc_hash_table_free(server->watcher_list_pk);
-
silc_hash_free(server->md5hash);
silc_hash_free(server->sha1hash);
- silc_hmac_unregister_all();
- silc_hash_unregister_all();
- silc_cipher_unregister_all();
- silc_pkcs_unregister_all();
+
+ silc_dlist_uninit(server->listeners);
+ silc_dlist_uninit(server->conns);
+ silc_dlist_uninit(server->expired_clients);
+ silc_skr_free(server->repository);
+ silc_packet_engine_stop(server->packet_engine);
silc_free(server->local_list);
silc_free(server->global_list);
silc_free(server->server_name);
- silc_free(server->id_string);
silc_free(server->purge_i);
silc_free(server->purge_g);
silc_free(server);
+
+ silc_hmac_unregister_all();
+ silc_hash_unregister_all();
+ silc_cipher_unregister_all();
+ silc_pkcs_unregister_all();
}
/* Creates a new server listener. */
silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
server);
server->local_list->servers =
- silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_SERVER, silc_idlist_server_destructor,
+ server);
server->local_list->channels =
- silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_CHANNEL, silc_idlist_channel_destructor,
+ NULL);
/* These are allocated for normal server as well as these hold some
global information that the server has fetched from its router. For
silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
server);
server->global_list->servers =
- silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_SERVER, silc_idlist_server_destructor,
+ server);
server->global_list->channels =
- silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL);
+ silc_idcache_alloc(0, SILC_ID_CHANNEL, silc_idlist_channel_destructor,
+ NULL);
/* Init watcher lists */
server->watcher_list =
if (!server->watcher_list_pk)
goto err;
- /* Init public key list */
- server->pk_hash =
- silc_hash_table_alloc(0, silc_hash_public_key, NULL,
- silc_hash_public_key_compare, NULL,
- NULL, NULL, TRUE);
-
- if (!server->pk_hash)
- goto err;
-
/* Create TCP listener */
listener = silc_server_listen(
server,
server->id = id;
server->server_name = server->config->server_info->server_name;
server->config->server_info->server_name = NULL;
+ silc_id_id2str(server->id, SILC_ID_SERVER, server->id_string,
+ sizeof(server->id_string), &server->id_string_len);
/* Add ourselves to the server list. We don't have a router yet
beacuse we haven't established a route yet. It will be done later.
if (silc_server_init_secondary(server) == FALSE)
goto err;
- /* Create connections to configured routers. */
- silc_server_create_connections(server);
-
server->listenning = TRUE;
- /* Allocate the entire socket list that is used in server. Eventually
- all connections will have entry in this table (it is a table of
- pointers to the actual object that is allocated individually
- later). */
- server->sockets = silc_calloc(server->config->param.connections_max,
- sizeof(*server->sockets));
- if (!server->sockets)
- goto err;
+ /* Create connections to configured routers. */
+ silc_server_create_connections(server);
/* If server connections has been configured then we must be router as
normal server cannot have server connections, only router connections. */
if (!server->packet_engine)
goto err;
+ /* Register client entry expiration timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_purge_expired_clients, server,
+ 600, 0);
+
+ /* Initialize HTTP server */
+ silc_server_http_init(server);
+
SILC_LOG_DEBUG(("Server initialized"));
/* We are done here, return succesfully */
{
SilcDList list;
SilcPacketStream ps;
+ SilcNetListener listener;
SILC_LOG_INFO(("SILC Server shutting down"));
/* We are not connected to network anymore */
server->standalone = TRUE;
+ silc_dlist_start(server->listeners);
+ while ((listener = silc_dlist_get(server->listeners)))
+ silc_net_close_listener(listener);
+
+ silc_server_http_uninit(server);
+
silc_schedule_stop(server->schedule);
silc_schedule_uninit(server->schedule);
server->schedule = NULL;
SILC_LOG_DEBUG(("Server stopped"));
}
-#if 0
-/* Parses whole packet, received earlier. */
+/* Purge expired client entries from the server */
-SILC_TASK_CALLBACK(silc_server_packet_parse_real)
+SILC_TASK_CALLBACK(silc_server_purge_expired_clients)
{
- SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
- SilcServer server = (SilcServer)parse_ctx->context;
- SilcPacketStream sock = parse_ctx->sock;
- SilcPacket *packet = parse_ctx->packet;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
- int ret;
-
- if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
- SILC_LOG_DEBUG(("Connection is disconnected"));
- goto out;
- }
-
- server->stat.packets_received++;
-
- /* Parse the packet */
- if (parse_ctx->normal)
- ret = silc_packet_parse(packet, idata ? idata->receive_key : NULL);
- else
- ret = silc_packet_parse_special(packet, idata ? idata->receive_key : NULL);
-
- /* If entry is disabled ignore what we got. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
- ret != SILC_PACKET_HEARTBEAT && ret != SILC_PACKET_RESUME_ROUTER &&
- ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE &&
- ret != SILC_PACKET_KEY_EXCHANGE_1 && ret != SILC_PACKET_KEY_EXCHANGE_2) {
- SILC_LOG_DEBUG(("Connection is disabled (packet %s dropped)",
- silc_get_packet_name(ret)));
- goto out;
- }
-
- if (ret == SILC_PACKET_NONE) {
- SILC_LOG_DEBUG(("Error parsing packet"));
- goto out;
- }
-
- /* Check that the the current client ID is same as in the client's packet. */
- if (sock->type == SILC_CONN_CLIENT) {
- SilcClientEntry client = (SilcClientEntry)sock->user_data;
- if (client && client->id && packet->src_id) {
- void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
- silc_free(id);
- SILC_LOG_DEBUG(("Packet source is not same as sender"));
- goto out;
- }
- silc_free(id);
- }
- }
-
- if (server->server_type == SILC_ROUTER) {
- /* Route the packet if it is not destined to us. Other ID types but
- server are handled separately after processing them. */
- if (packet->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
- packet->dst_id_type == SILC_ID_SERVER &&
- sock->type != SILC_CONN_CLIENT &&
- memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
- SilcPacketStream conn;
+ SilcServer server = context;
+ SilcClientEntry client;
+ SilcIDList id_list;
- /* Route the packet to fastest route for the destination ID */
- void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!id)
- goto out;
+ SILC_LOG_DEBUG(("Expire timeout"));
- conn = silc_server_route_get(server, id, packet->dst_id_type);
- if (!conn) {
- SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
- silc_id_render(id, SILC_ID_SERVER)));
- goto out;
- }
-
- silc_server_packet_route(server, conn, packet);
- silc_free(id);
- goto out;
- }
- }
+ silc_dlist_start(server->expired_clients);
+ while ((client = silc_dlist_get(server->expired_clients))) {
+ if (client->data.status & SILC_IDLIST_STATUS_REGISTERED)
+ continue;
- /* Parse the incoming packet type */
- silc_server_packet_parse_type(server, sock, packet);
+ id_list = (client->data.status & SILC_IDLIST_STATUS_LOCAL ?
+ server->local_list : server->global_list);
- /* Broadcast packet if it is marked as broadcast packet and it is
- originated from router and we are router. */
- if (server->server_type == SILC_ROUTER &&
- sock->type == SILC_CONN_ROUTER &&
- packet->flags & SILC_PACKET_FLAG_BROADCAST) {
- /* Broadcast to our primary route */
- silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
-
- /* If we have backup routers then we need to feed all broadcast
- data to those servers. */
- silc_server_backup_broadcast(server, sock, packet);
+ silc_idlist_del_data(client);
+ silc_idlist_del_client(id_list, client);
+ silc_dlist_del(server->expired_clients, client);
}
- out:
- silc_packet_context_free(packet);
- silc_free(parse_ctx);
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_purge_expired_clients, server,
+ 600, 0);
}
-#endif /* 0 */
/******************************* Connecting *********************************/
SilcUnknownEntry entry = silc_packet_get_context(sock);
SilcIDListData idata = (SilcIDListData)entry;
SilcServer server = entry->server;
- SilcServerConfigConnParams *param;
+ SilcServerConfigConnParams *param = &server->config->param;
SilcServerConnection sconn;
void *id_entry;
const char *hostname;
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);
+ SILC_SKR_USAGE_IDENTIFICATION, client,
+ NULL);
id_entry = (void *)client;
break;
sconn->remote_port = port;
silc_dlist_add(server->conns, sconn);
idata->sconn = sconn;
+ idata->last_receive = time(NULL);
/* Add the common data structure to the ID entry. */
silc_idlist_add_data(id_entry, (SilcIDListData)entry);
/* Connection has been fully established now. Everything is ok. */
SILC_LOG_DEBUG(("New connection authenticated"));
-
#if 0
/* Perform keepalive. */
if (param->keepalive_secs)
silc_socket_set_heartbeat(sock, param->keepalive_secs, server,
silc_server_perform_heartbeat,
server->schedule);
+#endif
/* Perform Quality of Service */
if (param->qos)
- silc_socket_set_qos(sock, param->qos_rate_limit, param->qos_bytes_limit,
- param->qos_limit_sec, param->qos_limit_usec,
- server->schedule);
-#endif
+ silc_socket_stream_set_qos(silc_packet_stream_get_stream(sock),
+ param->qos_rate_limit, param->qos_bytes_limit,
+ param->qos_limit_sec, param->qos_limit_usec);
silc_server_config_unref(&entry->cconfig);
silc_server_config_unref(&entry->sconfig);
/* Check for maximum allowed connections */
server->stat.conn_attempts++;
-#if 0
- if (silc_server_num_connections(server) >
+ if (silc_dlist_count(server->conns) >
server->config->param.connections_max) {
SILC_LOG_ERROR(("Refusing connection, server is full"));
server->stat.conn_failures++;
silc_stream_destroy(stream);
return;
}
-#endif
/* Get hostname, IP and port */
if (!silc_socket_stream_get_info(stream, NULL, (const char **)&hostname,
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),
+ idata ? SILC_CONNTYPE_STRING(idata->conn_type) : "",
tmp[0] ? tmp : ""));
// silc_socket_set_qos(sock, 0, 0, 0, 0, NULL);
/* Remove this client from watcher list if it is */
silc_server_del_from_watcher_list(server, client);
- /* Remove this client from the public key hash list */
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key, client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (client->data.public_key) {
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
+ client->data.public_key = NULL;
+ }
/* Update statistics */
server->stat.my_clients--;
SilcClientEntry client_entry = (SilcClientEntry)idata;
silc_server_free_client_data(server, sock, client_entry, TRUE,
signoff_message);
+ silc_packet_set_context(sock, NULL);
break;
}
silc_server_announce_channels(server, time(0) - 300,
backup_router->connection);
}
+
+ silc_packet_set_context(sock, NULL);
break;
}
silc_idlist_del_data(idata);
silc_free(entry);
+ silc_packet_set_context(sock, NULL);
break;
}
}
return TRUE;
}
-#if 0
-/* Timeout callback. This is called if connection is idle or for some
- other reason is not responding within some period of time. This
- disconnects the remote end. */
-
-SILC_TASK_CALLBACK(silc_server_timeout_remote)
-{
- SilcServer server = (SilcServer)context;
- SilcPacketStream sock = server->sockets[fd];
-
- SILC_LOG_DEBUG(("Start"));
-
- if (!sock)
- return;
-
- SILC_LOG_ERROR(("No response from %s (%s), Connection timeout",
- sock->hostname, sock->ip));
-
- /* If we have protocol active we must assure that we call the protocol's
- final callback so that all the memory is freed. */
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type != SILC_PROTOCOL_SERVER_BACKUP) {
- protocol = sock->protocol->protocol->type;
- silc_protocol_cancel(sock->protocol, server->schedule);
- sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
- silc_protocol_execute_final(sock->protocol, server->schedule);
- sock->protocol = NULL;
- return;
- }
-
- silc_server_disconnect_remote(server, sock,
- protocol ==
- SILC_PROTOCOL_SERVER_CONNECTION_AUTH ?
- SILC_STATUS_ERR_AUTH_FAILED :
- SILC_STATUS_ERR_KEY_EXCHANGE_FAILED,
- "Connection timeout");
-
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock, NULL);
-}
-#endif /* 0 */
-
/* Creates new channel. Sends NEW_CHANNEL packet to primary route. This
function may be used only by router. In real SILC network all channels
are created by routers thus this function is never used by normal
SilcBool get_secret,
SilcBuffer *user_mode_list);
void silc_server_stderr(SilcLogType type, char *message);
+void silc_server_http_init(SilcServer server);
+void silc_server_http_uninit(SilcServer server);
#endif
--- /dev/null
+/*
+
+ server_http.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "serverincludes.h"
+#include "server_internal.h"
+
+/************************* Types and definitions ****************************/
+
+#define HTTP_START1 \
+"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"" \
+"\"http://www.w3.ohtml4/strict.dtd\">\n" \
+"<html>\n" \
+"<head>\n" \
+"<meta http-equiv=\"Content-Type\" content=\"text/html; " \
+"charset=iso-8859-1\">\n" \
+"<title>\n"
+
+#define HTTP_START2 \
+"</title>\n" \
+"</head>\n" \
+"<body>\n"
+
+#define HTTP_END \
+"</body>\n" \
+"</html>\n"
+
+#define HTTP_404 "404 Not Found"
+#define HTTP_404_B "<body><h1>404 Not Found</h1><p>The page you are looking for cannot be located</body>"
+
+#define STAT_OUTPUT(fmt, stat) \
+do { \
+ silc_snprintf(buf, sizeof(buf), fmt "<br>", (int)stat); \
+ silc_buffer_strformat(&page, buf, SILC_STRFMT_END); \
+} while(0)
+
+
+/****************************** HTTP access *********************************/
+
+/* HTTP server callback. We serve pages here. */
+
+static void silc_server_http_callback(SilcHttpServer httpd,
+ SilcHttpConnection conn,
+ const char *uri,
+ const char *method,
+ SilcBuffer data,
+ void *context)
+{
+ SilcServer server = context;
+ SilcBufferStruct page;
+ unsigned char buf[128];
+
+ SILC_LOG_DEBUG(("HTTP callback: %s %s", method, uri));
+
+ memset(&page, 0, sizeof(page));
+
+ if (!strcasecmp(method, "GET")) {
+
+ /* Index page */
+ if (!strcmp(uri, "/") || !strcmp(uri, "/index.html")) {
+ SILC_LOG_DEBUG(("Index"));
+
+ silc_buffer_strformat(&page, HTTP_START1, SILC_STRFMT_END);
+ silc_buffer_strformat(&page, "SILC ",
+ server->server_type == SILC_ROUTER ?
+ "Router " : "Server ", server->server_name,
+ SILC_STRFMT_END);
+ silc_buffer_strformat(&page, HTTP_START2, SILC_STRFMT_END);
+
+ silc_buffer_strformat(&page, "<h1>SILC ",
+ server->server_type == SILC_ROUTER ?
+ "Router " : "Server ", server->server_name,
+ "</h1><hr><p>",
+ SILC_STRFMT_END);
+
+ silc_buffer_strformat(&page, "<b>Statistics:</b><p>", SILC_STRFMT_END);
+
+ STAT_OUTPUT("Clients : %d", server->stat.my_clients);
+ STAT_OUTPUT("Servers : %d", server->stat.my_servers);
+ STAT_OUTPUT("Routers : %d", server->stat.my_routers);
+ STAT_OUTPUT("Channels : %d", server->stat.my_channels);
+ STAT_OUTPUT("Joined users : %d", server->stat.my_chanclients);
+ STAT_OUTPUT("Aways : %d", server->stat.my_aways);
+ STAT_OUTPUT("Detached clients : %d", server->stat.my_detached);
+ STAT_OUTPUT("Server operators : %d", server->stat.my_server_ops);
+ STAT_OUTPUT("Router operators : %d", server->stat.my_router_ops);
+
+ silc_buffer_strformat(&page, "<p><b>Global Statistics:</b><p>",
+ SILC_STRFMT_END);
+ STAT_OUTPUT("Cell clients : %d", server->stat.cell_clients);
+ STAT_OUTPUT("Cell servers : %d", server->stat.cell_servers);
+ STAT_OUTPUT("Cell channels : %d", server->stat.cell_channels);
+ STAT_OUTPUT("Cell joined users : %d", server->stat.cell_chanclients);
+ STAT_OUTPUT("All clients : %d", server->stat.clients);
+ STAT_OUTPUT("All servers : %d", server->stat.servers);
+ STAT_OUTPUT("All routers : %d", server->stat.routers);
+ STAT_OUTPUT("All channels : %d", server->stat.channels);
+ STAT_OUTPUT("All joined users : %d", server->stat.chanclients);
+ STAT_OUTPUT("All aways : %d", server->stat.aways);
+ STAT_OUTPUT("All detached clients : %d", server->stat.detached);
+ STAT_OUTPUT("All server operators : %d", server->stat.server_ops);
+ STAT_OUTPUT("All router operators : %d", server->stat.router_ops);
+
+ silc_buffer_strformat(&page, "<p><b>Internal Statistics:</b><p>",
+ SILC_STRFMT_END);
+ STAT_OUTPUT("Connection attempts : %d", server->stat.conn_attempts);
+ STAT_OUTPUT("Connection failures : %d", server->stat.conn_failures);
+ STAT_OUTPUT("Authentication attempts : %d", server->stat.auth_attempts);
+ STAT_OUTPUT("Authentication failures : %d", server->stat.auth_failures);
+ STAT_OUTPUT("Packets sent : %d", server->stat.packets_sent);
+ STAT_OUTPUT("Packets received : %d", server->stat.packets_received);
+ STAT_OUTPUT("Commands sent : %d", server->stat.commands_sent);
+ STAT_OUTPUT("Commands received : %d", server->stat.commands_received);
+ STAT_OUTPUT("Connections : %d", server->stat.conn_num);
+
+ silc_buffer_strformat(&page, HTTP_END, SILC_STRFMT_END);
+
+ silc_http_server_send(httpd, conn, &page);
+ silc_buffer_purge(&page);
+ return;
+ }
+ }
+
+ silc_http_server_send_error(httpd, conn, HTTP_404, HTTP_404_B);
+}
+
+void silc_server_http_init(SilcServer server)
+{
+ /* Allocate HTTP server */
+ server->httpd = silc_http_server_alloc(server->config->httpd_ip,
+ server->config->httpd_port,
+ server->schedule,
+ silc_server_http_callback,
+ server);
+}
+
+void silc_server_http_uninit(SilcServer server)
+{
+ if (server->httpd)
+ silc_http_server_free(server->httpd);
+}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 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
*/
struct SilcServerStruct {
- char *server_name;
- SilcServerEntry id_entry;
- SilcServerID *id;
- unsigned char *id_string;
+ SilcSchedule schedule; /* Server scheduler */
+ SilcDList listeners; /* TCP listeners */
+ SilcPacketEngine packet_engine; /* Packet engine */
+ SilcDList conns; /* Connections in server */
+ SilcSKR repository; /* Public key repository */
+ SilcPublicKey public_key; /* Server public key */
+ SilcPrivateKey private_key; /* Server private key */
+ SilcDList expired_clients; /* Expired client entries */
+ SilcHttpServer httpd; /* HTTP server */
+
+ char *server_name; /* Server's name */
+ SilcServerEntry id_entry; /* Server's local entry */
+ SilcServerID *id; /* Server's ID */
+ unsigned char id_string[32]; /* Server's ID as string */
SilcUInt32 id_string_len;
- SilcUInt32 starttime;
-
- unsigned int server_type : 2; /* Server type (server.h) */
- unsigned int standalone : 1; /* Set if server is standalone, and
- does not have connection to network. */
- unsigned int listenning : 1; /* Set if server is listenning for
- incoming connections. */
- unsigned int background : 1; /* Set when server is on background */
- unsigned int backup_router : 1; /* Set if this is backup router */
- unsigned int backup_primary : 1; /* Set if we've switched our primary
- router to a backup router. */
- unsigned int backup_noswitch: 1; /* Set if we've won't switch to
- become primary (we are backup) */
- unsigned int backup_closed : 1; /* Set if backup closed connection.
- Do not allow resuming in this case. */
- unsigned int wait_backup : 1; /* Set if we are waiting for backup
- router to connect to us. */
- unsigned int server_shutdown: 1; /* Set when shutting down */
- unsigned int no_reconnect : 1; /* If set, server won't reconnect to
- router after disconnection. */
- unsigned int no_conf : 1; /* Set when connecting without
- configuration. */
+ SilcUInt32 starttime; /* Server start time */
SilcServerEntry router; /* Pointer to the primary router */
unsigned long router_connect; /* Time when router was connected */
/* Current command identifier, 0 not used */
SilcUInt16 cmd_ident;
- /* SILC server scheduler */
- SilcSchedule schedule;
-
/* ID lists. */
SilcIDList local_list;
SilcIDList global_list;
SilcHashTable watcher_list;
SilcHashTable watcher_list_pk;
- SilcDList listeners; /* TCP listeners */
- SilcPacketEngine packet_engine; /* Packet engine */
- SilcDList conns;
- SilcSKR repository;
-
- /* Table of connected sockets */
- SilcPacketStream *sockets;
-
- /* Server public key */
- SilcPublicKey public_key;
- SilcPrivateKey private_key;
-
/* Hash objects for general hashing */
SilcHash md5hash;
SilcHash sha1hash;
SilcIDListPurge purge_i;
SilcIDListPurge purge_g;
- /* Hash table for public keys of all clients */
- SilcHashTable pk_hash;
+ unsigned int server_type : 2; /* Server type (server.h) */
+ unsigned int standalone : 1; /* Set if server is standalone, and
+ does not have connection to network. */
+ unsigned int listenning : 1; /* Set if server is listenning for
+ incoming connections. */
+ unsigned int background : 1; /* Set when server is on background */
+ unsigned int backup_router : 1; /* Set if this is backup router */
+ unsigned int backup_primary : 1; /* Set if we've switched our primary
+ router to a backup router. */
+ unsigned int backup_noswitch: 1; /* Set if we've won't switch to
+ become primary (we are backup) */
+ unsigned int backup_closed : 1; /* Set if backup closed connection.
+ Do not allow resuming in this case. */
+ unsigned int wait_backup : 1; /* Set if we are waiting for backup
+ router to connect to us. */
+ unsigned int server_shutdown: 1; /* Set when shutting down */
+ unsigned int no_reconnect : 1; /* If set, server won't reconnect to
+ router after disconnection. */
+ unsigned int no_conf : 1; /* Set when connecting without
+ configuration. */
};
/* Failure context. This is allocated when failure packet is received.
SilcBool found;
} *SilcServerPublicKeyUser, SilcServerPublicKeyUserStruct;
-void silc_server_public_key_hash_foreach(void *key, void *context,
- void *user_context)
+/* SKR find callbcak */
+
+static void silc_server_query_skr_callback(SilcSKR skr,
+ SilcSKRFind find,
+ SilcSKRStatus status,
+ SilcDList keys,
+ void *context)
{
- SilcServerPublicKeyUser uc = user_context;
- SilcClientEntry entry = context;
+ SilcServerPublicKeyUser uc = context;
+ SilcSKRKey key;
- /* Nothing was found, just return */
- if (!context)
- return;
+ if (keys) {
+ (*uc->clients) = silc_realloc((*uc->clients),
+ sizeof((**uc->clients)) *
+ ((*uc->clients_count) +
+ silc_dlist_count(keys)));
- uc->found = TRUE;
+ silc_dlist_start(keys);
+ while ((key = silc_dlist_get(keys)))
+ (*uc->clients)[(*uc->clients_count)++] = key->key_context;
- (*uc->clients) = silc_realloc((*uc->clients),
- sizeof((**uc->clients)) *
- ((*uc->clients_count) + 1));
- (*uc->clients)[(*uc->clients_count)++] = entry;
+ uc->found = TRUE;
+ silc_dlist_uninit(keys);
+ }
+
+ silc_skr_find_free(find);
}
/* If clients are set, limit the found clients using the attributes in
SilcAttributePayload attr;
SilcAttribute attribute;
SilcAttributeObjPk pk;
- SilcPublicKey publickey;
+ SilcPublicKey publickey, cmp_pubkey;
SilcPKCSType type;
SilcBool found = FALSE, no_clients = FALSE;
int i;
continue;
}
- /* If no clients were set on calling this function, we
- just search for clients, otherwise we try to limit
- the clients */
+ /* If no clients were set on calling this function, we just search
+ for clients, otherwise we try to limit the clients. */
if (no_clients) {
SilcServerPublicKeyUserStruct usercontext;
+ SilcSKRFind find;
usercontext.clients = clients;
usercontext.clients_count = clients_count;
usercontext.found = FALSE;
- silc_hash_table_find_foreach(server->pk_hash, publickey,
- silc_server_public_key_hash_foreach,
- &usercontext);
+ find = silc_skr_find_alloc();
+ if (!find)
+ continue;
+
+ silc_skr_find_set_public_key(find, publickey);
+ silc_skr_find_set_usage(find, SILC_SKR_USAGE_IDENTIFICATION);
+ silc_skr_find(server->repository, server->schedule,
+ find, silc_server_query_skr_callback, &usercontext);
if (usercontext.found == TRUE)
found = TRUE;
if (!entry->data.public_key)
continue;
- if (!silc_hash_table_find_by_context(server->pk_hash, publickey,
- entry, NULL))
- (*clients)[i] = NULL;
- else
- found = TRUE;
+ if (silc_server_get_public_key_by_client(server, entry,
+ &cmp_pubkey)) {
+ if (silc_pkcs_public_key_compare(cmp_pubkey, publickey)) {
+ found = TRUE;
+ continue;
+ }
+ }
+
+ (*clients)[i] = NULL;
}
}
silc_free(pk.type);
SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (client->data.public_key) {
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
+ client->data.public_key = NULL;
+ }
+
silc_server_remove_clients_channels(server, entry, clients,
client, channels);
silc_server_del_from_watcher_list(server, client);
client->mode = 0;
client->router = NULL;
client->connection = NULL;
+ silc_dlist_add(server->expired_clients, client);
} else {
silc_idlist_del_data(client);
silc_idlist_del_client(server->local_list, client);
SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
- if (client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- client->data.public_key,
- client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (client->data.public_key) {
+ silc_skr_del_public_key(server->repository, client->data.public_key,
+ client);
+ client->data.public_key = NULL;
+ }
+
silc_server_remove_clients_channels(server, entry, clients,
client, channels);
silc_server_del_from_watcher_list(server, client);
client->mode = 0;
client->router = NULL;
client->connection = NULL;
+ silc_dlist_add(server->expired_clients, client);
} else {
silc_idlist_del_data(client);
silc_idlist_del_client(server->global_list, client);
silc_skr_find_free(find);
}
-/* Get public key. For public key tables that has multiple keys in it the
- silc_server_find_public_key must be used. */
+/* Get public key by key usage and key context. */
SilcPublicKey silc_server_get_public_key(SilcServer server,
SilcSKRKeyUsage usage,
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)
{
SilcBool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
SilcBool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
- if (remote_client->data.public_key)
- silc_hash_table_del_by_context(server->pk_hash,
- remote_client->data.public_key,
- remote_client);
+ /* Remove client's public key from repository, this will free it too. */
+ if (remote_client->data.public_key) {
+ silc_skr_del_public_key(server->repository,
+ remote_client->data.public_key, remote_client);
+ remote_client->data.public_key = NULL;
+ }
if (SILC_IS_LOCAL(remote_client)) {
server->stat.my_clients--;
notify change of notify type indicated by `notify'. */
SilcBool silc_server_check_watcher_list(SilcServer server,
- SilcClientEntry client,
- const char *new_nick,
- SilcNotifyType notify)
+ SilcClientEntry client,
+ const char *new_nick,
+ SilcNotifyType notify)
{
unsigned char hash[16];
WatcherNotifyContext n;
is not watching any nicknames. */
SilcBool silc_server_del_from_watcher_list(SilcServer server,
- SilcClientEntry client)
+ SilcClientEntry client)
{
SilcHashTableList htl;
void *key;
/* Process invite or ban information */
-SilcBool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
- SilcUInt8 action, SilcArgumentPayload args)
+SilcBool silc_server_inviteban_process(SilcServer server,
+ SilcHashTable list,
+ SilcUInt8 action,
+ SilcArgumentPayload args)
{
unsigned char *tmp;
SilcUInt32 type, len;
on the `channel' public key list. */
SilcBool silc_server_verify_channel_auth(SilcServer server,
- SilcChannelEntry channel,
- SilcClientID *client_id,
- const unsigned char *auth,
- SilcUInt32 auth_len)
+ SilcChannelEntry channel,
+ SilcClientID *client_id,
+ const unsigned char *auth,
+ SilcUInt32 auth_len)
{
SilcAuthPayload ap;
SilcPublicKey chpk;
/* Add the public key to repository */
if (silc_skr_add_public_key(skr, public_key, usage,
- key_context ? key_context : (void *)usage) !=
- SILC_SKR_OK) {
+ key_context ? key_context : (void *)usage,
+ NULL) != SILC_SKR_OK) {
SILC_SERVER_LOG_ERROR(("Error while adding public key \"%s\"", p));
return FALSE;
}
CONFIG_IS_DOUBLE(config->debug_string);
config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
}
+ else if (!strcmp(name, "http_server")) {
+ config->httpd = *(SilcBool *)val;
+ }
+ else if (!strcmp(name, "http_server_ip")) {
+ CONFIG_IS_DOUBLE(config->httpd_ip);
+ config->httpd_ip = (*(char *)val ? strdup((char *) val) : NULL);
+ }
+ else if (!strcmp(name, "http_server_port")) {
+ int port = *(int *)val;
+ if ((port <= 0) || (port > 65535)) {
+ SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+ "Invalid port number!"));
+ got_errno = SILC_CONFIG_EPRINTLINE;
+ goto got_err;
+ }
+ config->httpd_port = (SilcUInt16)port;
+ }
else
return SILC_CONFIG_EINTERNAL;
{ "qos_limit_usec", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
{ "channel_join_limit", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
{ "debug_string", SILC_CONFIG_ARG_STR, fetch_generic, NULL },
+ { "http_server", SILC_CONFIG_ARG_TOGGLE, fetch_generic, NULL },
+ { "http_server_ip", SILC_CONFIG_ARG_STRE, fetch_generic, NULL },
+ { "http_server_port", SILC_CONFIG_ARG_INT, fetch_generic, NULL },
{ 0, 0, 0, 0 }
};
silc_free(config->param.version_protocol);
silc_free(config->param.version_software);
silc_free(config->param.version_software_vendor);
+ silc_free(config->httpd_ip);
/* Destroy Logging channels */
if (config->logging_info)
SilcBool logging_quick;
long logging_flushdelay;
char *debug_string;
+ SilcBool httpd;
+ char *httpd_ip;
+ SilcUInt16 httpd_port;
/* Other configuration sections */
SilcServerConfigCipher *cipher;
fprintf(fdd, " primary router : %s\n",
silcd->router->server_name ? silcd->router->server_name : "");
-#if 0
- /* Dump socket connections */
+ /* Dump connections */
{
- int i;
SilcPacketStream s;
-
- fprintf(fdd, "\nDumping socket connections\n");
- for (i = 0; i < silcd->config->param.connections_max; i++) {
- s = silcd->sockets[i];
- if (!s)
- continue;
- fprintf(fdd, " %d: host %s ip %s port %d type %d flags 0x%x\n",
- s->sock, s->hostname ? s->hostname : "N/A",
- s->ip ? s->ip : "N/A", s->port, s->type,
- (unsigned int)s->flags);
+ SilcDList conns = silc_packet_engine_get_streams(silcd->packet_engine);
+
+ fprintf(fdd, "\nDumping connections\n");
+ silc_dlist_start(conns);
+ while ((s = silc_dlist_get(conns))) {
+ const char *hostname, *ip;
+ SilcUInt16 port;
+ SilcSocket sock;
+ SilcIDListData idata = silc_packet_get_context(s);
+ if (!silc_socket_stream_get_info(silc_packet_stream_get_stream(s),
+ &sock, &hostname, &ip, &port))
+ continue;
+ fprintf(fdd, " %d: host %s ip %s port %d type %d\n",
+ sock, hostname ? hostname : "N/A",
+ ip ? ip : "N/A", port, idata ? idata->conn_type : 0);
}
+ silc_dlist_uninit(conns);
}
-#endif
/* Dump lists */
{