unsigned int arg_type,
unsigned char *arg,
unsigned int arg_len);
-void silc_server_command_send_users(SilcServer server,
- SilcSocketConnection sock,
- SilcChannelEntry channel,
- int pending);
/* Server command list. */
SilcServerCommand silc_command_list[] =
*client_id_count = 1;
/* Take all ID's from the command packet */
- if (argc > 3) {
- for (k = 1, i = 4; i < argc + 1; i++) {
- tmp = silc_argument_get_arg_type(cmd->args, i, &len);
+ if (argc > 1) {
+ for (k = 1, i = 1; i < argc; i++) {
+ tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
if (tmp) {
*client_id = silc_realloc(*client_id, sizeof(**client_id) *
(*client_id_count + 1));
SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
- /* XXX */
- if (entry->userinfo)
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, ident, 5,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 5, entry->userinfo,
- strlen(entry->userinfo),
- 7, idle, 4);
- else
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, ident, 4,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 7, idle, 4);
+ packet =
+ silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
+ status, ident, 5,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh),
+ 5, entry->userinfo,
+ strlen(entry->userinfo),
+ 7, idle, 4);
}
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
clients = silc_idlist_get_clients_by_nickname(server->local_list,
nick, server_name,
&clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->local_list,
+ nick, server->md5hash,
+ &clients_count);
}
/* Check global list as well */
clients = silc_idlist_get_clients_by_nickname(server->global_list,
nick, server_name,
&clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->global_list,
+ nick, server->md5hash,
+ &clients_count);
}
}
if (!entry->username) {
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- SILC_STATUS_OK, ident, 2,
+ status, ident, 2,
2, idp->data, idp->len,
3, nh, strlen(nh));
} else {
}
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
- SILC_STATUS_OK, ident, 3,
+ status, ident, 3,
2, idp->data, idp->len,
3, nh, strlen(nh),
4, uh, strlen(uh));
clients = silc_idlist_get_clients_by_nickname(server->local_list,
nick, server_name,
&clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->local_list,
+ nick, server->md5hash,
+ &clients_count);
}
/* Check global list as well */
clients = silc_idlist_get_clients_by_nickname(server->global_list,
nick, server_name,
&clients_count);
+ if (!clients)
+ clients = silc_idlist_get_clients_by_hash(server->global_list,
+ nick, server->md5hash,
+ &clients_count);
}
}
goto out;
}
+ if (strlen(nick) > 128)
+ nick[127] = '\0';
+
/* Create new Client ID */
silc_id_create_client_id(cmd->server->id, cmd->server->rng,
cmd->server->md5hash, nick,
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
}
if (argc > 1) {
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
}
/* Check whether the sender of this command is on the channel. */
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
+ if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+ goto out;
+
/* Get destination ID */
tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
if (len > 128)
silc_server_command_quit_cb, (void *)q,
0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ out:
silc_server_command_free(cmd);
}
silc_server_command_free(cmd);
}
-/* Assembles USERS command and executes it. This is called when client
- joins to a channel and we wan't to send USERS command reply to the
- client. */
-
-void silc_server_command_send_users(SilcServer server,
- SilcSocketConnection sock,
- SilcChannelEntry channel,
- int pending)
-{
- SilcServerCommandContext cmd;
- SilcBuffer buffer, idp;
- SilcPacketContext *packet = silc_packet_context_alloc();
-
- SILC_LOG_DEBUG(("Start"));
-
- /* Create USERS command packet and process it. */
- idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
- buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
- 1, idp->data, idp->len);
-
- packet->buffer = silc_buffer_copy(buffer);
- packet->sock = sock;
- packet->type = SILC_PACKET_COMMAND;
-
- cmd = silc_server_command_alloc();
- cmd->payload = silc_command_payload_parse(buffer);
- if (!cmd->payload) {
- silc_free(cmd);
- silc_buffer_free(buffer);
- silc_buffer_free(idp);
- silc_packet_context_free(packet);
- return;
- }
- cmd->args = silc_command_get_args(cmd->payload);
- cmd->server = server;
- cmd->sock = silc_socket_dup(sock);
- cmd->packet = silc_packet_context_dup(packet);
- cmd->pending = FALSE;
-
- if (pending) {
- /* If this function was called from pending command then instead of
- processing the command now, register a pending command callback which
- will process it after we've received the automatic USERS command
- reply which server will send in JOIN. */
- silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
- silc_server_command_users, cmd);
- cmd->pending = TRUE;
- silc_buffer_free(buffer);
- silc_buffer_free(idp);
- return;
- }
-
- /* Process USERS command. */
- silc_server_command_users((void *)cmd);
-
- silc_buffer_free(buffer);
- silc_buffer_free(idp);
- silc_packet_context_free(packet);
-}
-
/* Internal routine to join channel. The channel sent to this function
has been either created or resolved from ID lists. This joins the sent
client to the channel. */
{
SilcSocketConnection sock = cmd->sock;
unsigned char *tmp;
- unsigned int tmp_len;
- unsigned char *passphrase = NULL, mode[4], tmp2[4];
+ unsigned int tmp_len, user_count;
+ unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
SilcClientEntry client;
SilcChannelClientEntry chl;
- SilcBuffer reply, chidp, clidp, keyp;
+ SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
unsigned short ident = silc_command_get_ident(cmd->payload);
SILC_LOG_DEBUG(("Start"));
}
/* Generate new channel key as protocol dictates */
- if (!created || !channel->channel_key)
+ if ((!created && silc_list_count(channel->user_list) > 0) ||
+ !channel->channel_key)
silc_server_create_channel_key(server, channel, 0);
/* Send the channel key. This is broadcasted to the channel but is not
sent to the client who is joining to the channel. */
silc_server_send_channel_key(server, NULL, channel,
server->server_type == SILC_ROUTER ?
- FALSE : server->standalone);
+ FALSE : !server->standalone);
/* Join the client to the channel by adding it to channel's user list.
Add also the channel to client entry's channels list for fast cross-
silc_list_add(channel->user_list, chl);
silc_list_add(client->channels, chl);
+ /* Get users on the channel */
+ silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
+ &user_count);
+
/* Encode Client ID Payload of the original client who wants to join */
clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
SILC_PUT32_MSB(channel->mode, mode);
SILC_PUT32_MSB(created, tmp2);
+ SILC_PUT32_MSB(user_count, tmp3);
tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
strlen(channel->channel_key->
if (!channel->topic) {
reply =
silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
- SILC_STATUS_OK, ident, 5,
+ SILC_STATUS_OK, ident, 9,
2, channel->channel_name,
strlen(channel->channel_name),
3, chidp->data, chidp->len,
- 4, mode, 4,
- 5, tmp2, 4,
- 6, keyp->data, keyp->len);
+ 4, clidp->data, clidp->len,
+ 5, mode, 4,
+ 6, tmp2, 4,
+ 7, keyp->data, keyp->len,
+ 12, tmp3, 4,
+ 13, user_list->data, user_list->len,
+ 14, mode_list->data,
+ mode_list->len);
} else {
reply =
silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
- SILC_STATUS_OK, ident, 6,
+ SILC_STATUS_OK, ident, 10,
2, channel->channel_name,
strlen(channel->channel_name),
3, chidp->data, chidp->len,
- 4, mode, 4,
- 5, tmp2, 4,
- 6, keyp->data, keyp->len,
- 8, channel->topic,
- strlen(channel->topic));
+ 4, clidp->data, clidp->len,
+ 5, mode, 4,
+ 6, tmp2, 4,
+ 7, keyp->data, keyp->len,
+ 10, channel->topic,
+ strlen(channel->topic),
+ 12, tmp3, 4,
+ 13, user_list->data, user_list->len,
+ 14, mode_list->data,
+ mode_list->len);
}
/* Send command reply */
SILC_ID_CLIENT_LEN);
}
- /* Send USERS command reply to the joined channel so the user sees who
- is currently on the channel. */
- silc_server_command_send_users(server, sock, channel, cmd->pending);
-
silc_buffer_free(reply);
silc_buffer_free(clidp);
silc_buffer_free(chidp);
silc_buffer_free(keyp);
+ silc_buffer_free(user_list);
+ silc_buffer_free(mode_list);
out:
if (passphrase)
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
int tmp_len;
- char *tmp, *channel_name = NULL, *cipher = NULL;
+ char *tmp, *channel_name = NULL, *cipher, *hmac;
SilcChannelEntry channel;
unsigned int umode = 0;
int created = FALSE;
}
channel_name = tmp;
+ if (strlen(channel_name) > 256)
+ channel_name[255] = '\0';
+
if (silc_server_command_bad_chars(channel_name) == TRUE) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_CHANNEL);
goto out;
}
- /* Get cipher name */
+ /* Get cipher and hmac name */
cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
+ hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
/* See if the channel exists */
channel = silc_idlist_find_channel_by_name(server->local_list,
the channel by ourselves. */
if (server->standalone) {
channel = silc_server_create_new_channel(server, server->id, cipher,
- channel_name, TRUE);
+ hmac, channel_name, TRUE);
umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
created = TRUE;
if (!channel) {
/* Channel really does not exist, create it */
channel = silc_server_create_new_channel(server, server->id, cipher,
- channel_name, TRUE);
+ hmac, channel_name, TRUE);
umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
created = TRUE;
}
if (!channel) {
/* Channel really does not exist, create it */
channel = silc_server_create_new_channel(server, server->id, cipher,
- channel_name, TRUE);
+ hmac, channel_name, TRUE);
umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
created = TRUE;
}
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
}
/* Check whether this client is on the channel */
if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
/* Cipher to use protect the traffic */
- unsigned int key_len = 256;
- char *cp;
+ unsigned int key_len;
/* Get cipher */
tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
if (!tmp) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
- cp = strchr(tmp, ':');
- if (cp) {
- key_len = atoi(cp);
- *cp = '\0';
- }
-
/* XXX Duplicated code, make own function for this!! */
/* Delete old cipher and allocate the new one */
SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
goto out;
}
-
- key_len /= 8;
- if (key_len > 32)
- key_len = 32;
+ key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
/* Re-generate channel key */
silc_server_create_channel_key(server, channel, key_len);
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
}
/* Check whether sender is on the channel */
channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
}
/* Check whether sender is on the channel */
to the client who joined the channel. */
silc_server_send_channel_key(server, target_client->connection, channel,
server->server_type == SILC_ROUTER ?
- FALSE : server->standalone);
+ FALSE : !server->standalone);
out:
silc_server_command_free(cmd);
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
}
/* Check whether this client is on the channel */
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcChannelEntry channel;
- SilcChannelClientEntry chl;
SilcChannelID *id;
SilcBuffer packet;
unsigned char *channel_id;
unsigned int channel_id_len;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
- SilcBuffer idp;
unsigned char lc[4];
unsigned int list_count = 0;
unsigned short ident = silc_command_get_ident(cmd->payload);
}
}
- /* Assemble the lists now */
-
- client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
- silc_list_count(channel->user_list));
- silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
- client_mode_list =
- silc_buffer_alloc(4 * silc_list_count(channel->user_list));
- silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
-
- silc_list_start(channel->user_list);
- while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
- /* Client ID */
- idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
- silc_buffer_put(client_id_list, idp->data, idp->len);
- silc_buffer_pull(client_id_list, idp->len);
- silc_buffer_free(idp);
-
- /* Client's mode on channel */
- SILC_PUT32_MSB(chl->mode, client_mode_list->data);
- silc_buffer_pull(client_mode_list, 4);
-
- list_count++;
- }
- silc_buffer_push(client_id_list,
- client_id_list->data - client_id_list->head);
- silc_buffer_push(client_mode_list,
- client_mode_list->data - client_mode_list->head);
+ /* Get the users list */
+ silc_server_get_users_on_channel(server, channel, &client_id_list,
+ &client_mode_list, &list_count);
/* List count */
SILC_PUT32_MSB(list_count, lc);