{
unsigned char *public_key;
unsigned char *private_key;
- unsigned int pk_len, prv_len;
+ uint32 pk_len, prv_len;
struct stat st;
if (stat("pubkey.pub", &st) < 0 && stat("privkey.prv", &st) < 0) {
/* Creates connection to a remote router. */
void silc_server_create_connection(SilcServer server,
- char *remote_host, unsigned int port)
+ char *remote_host, uint32 port)
{
SilcServerConnection sconn;
{
SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
- /* Send REMOVE_ID packet to routers. */
- if (!server->standalone && server->router)
- silc_server_send_notify_server_signoff(server,
- server->router->connection,
- server->server_type ==
- SILC_SERVER ?
- FALSE : TRUE, user_data->id,
- SILC_ID_SERVER_LEN);
-
- /* Then also free all client entries that this server owns as
- they will become invalid now as well. */
- silc_server_remove_clients_by_server(server, user_data);
+ /* Free all client entries that this server owns as they will
+ become invalid now as well. */
+ silc_server_remove_clients_by_server(server, user_data, TRUE);
/* If this was our primary router connection then we're lost to
the outside world. */
/* This function is used to remove all client entries by the server `entry'.
This is called when the connection is lost to the server. In this case
- we must invalidate all the client entries owned by the server `entry'. */
+ we must invalidate all the client entries owned by the server `entry'.
+ If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
+ distributed to our local clients. */
int silc_server_remove_clients_by_server(SilcServer server,
- SilcServerEntry entry)
+ SilcServerEntry entry,
+ int server_signoff)
{
SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client = NULL;
+ SilcBuffer idp;
+ SilcClientEntry *clients = NULL;
+ uint32 clients_c = 0;
+ unsigned char **argv = NULL;
+ uint32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
+ int i;
SILC_LOG_DEBUG(("Start"));
+ if (server_signoff) {
+ idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
+ argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+ argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
+ argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
+ argv[argc] = idp->data;
+ argv_lens[argc] = idp->len;
+ argv_types[argc] = argc + 1;
+ argc++;
+ silc_buffer_free(idp);
+ }
+
if (silc_idcache_find_by_id(server->local_list->clients,
SILC_ID_CACHE_ANY, SILC_ID_CLIENT, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
client = (SilcClientEntry)id_cache->context;
-
+ if (client->data.registered == FALSE) {
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ else
+ continue;
+ }
+
if (client->router != entry) {
+ if (server_signoff && client->connection) {
+ clients = silc_realloc(clients,
+ sizeof(*clients) * (clients_c + 1));
+ clients[clients_c] = client;
+ clients_c++;
+ }
+
if (!silc_idcache_list_next(list, &id_cache))
break;
else
continue;
}
+ if (server_signoff) {
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+ argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
+ (argc + 1));
+ argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
+ (argc + 1));
+ argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
+ memcpy(argv[argc], idp->data, idp->len);
+ argv_lens[argc] = idp->len;
+ argv_types[argc] = argc + 1;
+ argc++;
+ silc_buffer_free(idp);
+ }
+
/* Remove the client entry */
- silc_server_remove_from_channels(server, NULL, client, TRUE,
- NULL, TRUE);
+ silc_server_remove_from_channels(server, NULL, client, FALSE,
+ NULL, FALSE);
silc_idlist_del_client(server->local_list, client);
if (!silc_idcache_list_next(list, &id_cache))
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
client = (SilcClientEntry)id_cache->context;
+ if (client->data.registered == FALSE) {
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ else
+ continue;
+ }
if (client->router != entry) {
+ if (server_signoff && client->connection) {
+ clients = silc_realloc(clients,
+ sizeof(*clients) * (clients_c + 1));
+ clients[clients_c] = client;
+ clients_c++;
+ }
+
if (!silc_idcache_list_next(list, &id_cache))
break;
else
continue;
}
+ if (server_signoff) {
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+ argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
+ (argc + 1));
+ argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
+ (argc + 1));
+ argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
+ memcpy(argv[argc], idp->data, idp->len);
+ argv_lens[argc] = idp->len;
+ argv_types[argc] = argc + 1;
+ argc++;
+ silc_buffer_free(idp);
+ }
+
/* Remove the client entry */
- silc_server_remove_from_channels(server, NULL, client, TRUE,
- NULL, TRUE);
+ silc_server_remove_from_channels(server, NULL, client, FALSE,
+ NULL, FALSE);
silc_idlist_del_client(server->global_list, client);
if (!silc_idcache_list_next(list, &id_cache))
}
silc_idcache_list_free(list);
}
-
+
+ /* Send the SERVER_SIGNOFF notify */
+ if (server_signoff) {
+ SilcBuffer args;
+
+ /* Send SERVER_SIGNOFF notify to our primary router */
+ if (!server->standalone && server->router) {
+ args = silc_argument_payload_encode(1, argv, argv_lens,
+ argv_types);
+ silc_server_send_notify_args(server,
+ server->router->connection,
+ server->server_type ==
+ SILC_SERVER ? FALSE : TRUE,
+ SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+ argc, args);
+ silc_buffer_free(args);
+ }
+
+ args = silc_argument_payload_encode(argc, argv, argv_lens,
+ argv_types);
+ /* Send to local clients */
+ for (i = 0; i < clients_c; i++) {
+ silc_server_send_notify_args(server, clients[i]->connection,
+ FALSE, SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+ argc, args);
+ }
+
+ silc_free(clients);
+ silc_buffer_free(args);
+ silc_free(argv);
+ silc_free(argv_lens);
+ silc_free(argv_types);
+ }
+
return TRUE;
}
silc_list_count(channel->user_list) < 2) {
server->stat.my_channels--;
+ if (channel->rekey)
+ silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
+
if (channel->founder_key) {
/* The founder auth data exists, do not remove the channel entry */
SilcChannelClientEntry chl2;
- silc_free(channel->id);
channel->id = NULL;
silc_list_start(channel->user_list);
server->stat.my_channels--;
+ if (channel->rekey)
+ silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
+
if (channel->founder_key) {
/* The founder auth data exists, do not remove the channel entry */
SilcChannelClientEntry chl2;
- silc_free(channel->id);
channel->id = NULL;
silc_list_start(channel->user_list);
silc_server_create_channel_key(server, channel, 0);
/* Send the channel key to the channel. The key of course is not sent
- to the client who was removed f rom the channel. */
+ to the client who was removed from the channel. */
silc_server_send_channel_key(server, client->connection, channel,
server->server_type == SILC_ROUTER ?
FALSE : !server->standalone);
/* Remove channel if there is no users anymore */
if (server->server_type == SILC_ROUTER &&
silc_list_count(channel->user_list) < 2) {
+ if (channel->rekey)
+ silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
if (!silc_idlist_del_channel(server->local_list, channel))
silc_idlist_del_channel(server->global_list, channel);
silc_buffer_free(clidp);
server->stat.my_channels--;
silc_buffer_free(clidp);
+ if (channel->rekey)
+ silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
+
if (channel->founder_key) {
/* The founder auth data exists, do not remove the channel entry */
SilcChannelClientEntry chl2;
- silc_free(channel->id);
channel->id = NULL;
silc_list_start(channel->user_list);
return entry;
}
+/* Channel's key re-key timeout callback. */
+
+SILC_TASK_CALLBACK(silc_server_channel_key_rekey)
+{
+ SilcServerChannelRekey rekey = (SilcServerChannelRekey)context;
+ SilcServer server = (SilcServer)rekey->context;
+
+ silc_server_create_channel_key(server, rekey->channel, rekey->key_len);
+ silc_server_send_channel_key(server, NULL, rekey->channel, FALSE);
+
+ silc_task_register(server->timeout_queue, 0,
+ silc_server_channel_key_rekey,
+ (void *)rekey, 3600, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+}
+
/* Generates new channel key. This is used to create the initial channel key
but also to re-generate new key for channel. If `key_len' is provided
it is the bytes of the key length. */
void silc_server_create_channel_key(SilcServer server,
SilcChannelEntry channel,
- unsigned int key_len)
+ uint32 key_len)
{
int i;
unsigned char channel_key[32], hash[32];
- unsigned int len;
+ uint32 len;
SILC_LOG_DEBUG(("Generating channel key"));
silc_hash_make(channel->hmac->hash, channel->key, len, hash);
silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
memset(hash, 0, sizeof(hash));
+
+ if (server->server_type == SILC_ROUTER) {
+ if (!channel->rekey)
+ channel->rekey = silc_calloc(1, sizeof(*channel->rekey));
+ channel->rekey->context = (void *)server;
+ channel->rekey->channel = channel;
+ channel->rekey->key_len = key_len;
+
+ silc_task_unregister_by_callback(server->timeout_queue,
+ silc_server_channel_key_rekey);
+ silc_task_register(server->timeout_queue, 0,
+ silc_server_channel_key_rekey,
+ (void *)channel->rekey, 3600, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
}
/* Saves the channel key found in the encoded `key_payload' buffer. This
SilcChannelKeyPayload payload = NULL;
SilcChannelID *id = NULL;
unsigned char *tmp, hash[32];
- unsigned int tmp_len;
+ uint32 tmp_len;
char *cipher;
SILC_LOG_DEBUG(("Start"));
memset(hash, 0, sizeof(hash));
memset(tmp, 0, tmp_len);
+ if (server->server_type == SILC_ROUTER) {
+ if (!channel->rekey)
+ channel->rekey = silc_calloc(1, sizeof(*channel->rekey));
+ channel->rekey->context = (void *)server;
+ channel->rekey->channel = channel;
+
+ silc_task_unregister_by_callback(server->timeout_queue,
+ silc_server_channel_key_rekey);
+ silc_task_register(server->timeout_queue, 0,
+ silc_server_channel_key_rekey,
+ (void *)channel->rekey, 3600, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+ }
+
out:
if (id)
silc_free(id);
}
static SilcBuffer
-silc_server_announce_encode_join(unsigned int argc, ...)
+silc_server_announce_encode_join(uint32 argc, ...)
{
va_list ap;
SilcIDCacheEntry id_cache;
SilcChannelEntry channel;
unsigned char *cid;
- unsigned short name_len;
+ uint16 name_len;
int len;
SILC_LOG_DEBUG(("Start"));
SilcChannelEntry channel,
SilcBuffer *user_list,
SilcBuffer *mode_list,
- unsigned int *user_count)
+ uint32 *user_count)
{
SilcChannelClientEntry chl;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
SilcBuffer idp;
- unsigned int list_count = 0;
+ uint32 list_count = 0;
client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
silc_list_count(channel->user_list));
SilcClientID *noadd,
SilcBuffer user_list,
SilcBuffer mode_list,
- unsigned int user_count)
+ uint32 user_count)
{
int i;
whenever server sends notify message to channel. It means two things;
some user has joined or leaved the channel. XXX TODO! */
for (i = 0; i < user_count; i++) {
- unsigned short idp_len;
- unsigned int mode;
+ uint16 idp_len;
+ uint32 mode;
SilcClientID *client_id;
SilcClientEntry client;
SilcSocketConnection silc_server_get_client_route(SilcServer server,
unsigned char *id_data,
- unsigned int id_len,
+ uint32 id_len,
SilcClientID *client_id,
SilcIDListData *idata)
{
SilcChannelEntry channel;
SilcChannelClientEntry chl;
unsigned char *cid;
- unsigned short name_len;
+ uint16 name_len;
int len;
silc_list_start(client->channels);