+Sun Mar 25 13:52:51 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Implemented the BAN command to the client library.
+
+ * The JOIN command in the server now checks the invite list
+ and the ban list.
+
+ * Changed the silc_command_reply_payload_encode_va and the
+ silc_command_payload_encode_va to support that if argument is
+ NULL it ignores and checks the next argument. Affected file
+ lib/silccore/silccommand.c.
+
+ * Added silc_server_send_notify_ban to send the BAN notify
+ type between routers.
+
+ * Chaned the silc_notify_payload_encode to support that if
+ argument is NULL it ignores and checks the next argument.
+ Affected file lib/silccore/silcnotify.c.
+
+ * Tested ban lists in router environment successfully.
+
+Sat Mar 24 14:47:25 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Implemented BAN command to the server, in silcd/command.[ch].
+
+ * Removed the BAN and INVITE_LIST modes from the CMODE command
+ in the server code.
+
+ * Added function silc_string_match to regex match two strings.
+ Affected files lib/silcutil/silcutil.[ch].
+
+Fri Mar 23 22:02:40 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Redefined parts of the SilcChannelEntry in the server to support
+ the new ban and invite lists.
+
Fri Mar 23 16:25:11 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Redefined the INVITE command. The same command can be used to
l <limit> Set/unset channel's user limit
a <passphrase> Set/unset passphrase for channel that must
be provided when joining to the channel.
- b <username!nickname@server>
- Add client to/remove client from ban list
- I <username!nickname@server>
- Add client to/remove client from invite list
- c <cipher>
- Set/unset channel's cipher
+ c <cipher> Set/unset channel's cipher
Multiple modes can be set/unset at once if the modes does not
require any arguments. If mode requires an argument then only
silc_screen_print_bottom_line(app->screen, 0);
break;
}
+ }
break;
+
+ case SILC_COMMAND_BAN:
+ {
+ SilcChannelEntry channel;
+ char *ban_list;
+
+ if (!success)
+ return;
+
+ channel = va_arg(vp, SilcChannelEntry);
+ ban_list = va_arg(vp, char *);
+
+ if (ban_list)
+ silc_say(client, conn, "%s ban list: %s", channel->channel_name,
+ ban_list);
+ else
+ silc_say(client, conn, "%s ban list not set", channel->channel_name);
}
+ break;
+
+ default:
+ break;
}
}
SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
+ SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
{ NULL, 0 },
};
SilcChannelClientEntry chl;
SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
unsigned short ident = silc_command_get_ident(cmd->payload);
+ char check[512];
SILC_LOG_DEBUG(("Start"));
if (!channel)
return;
- /* Get passphrase */
- tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
- if (tmp) {
- passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
- memcpy(passphrase, tmp, tmp_len);
+ /* Get the client entry */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+ client = (SilcClientEntry)sock->user_data;
+ } else {
+ client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ NULL);
+ if (!client)
+ goto out;
}
-
+
/*
* Check channel modes
*/
- /* Check invite list if channel is invite-only channel */
- if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
- if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
- /* Invite list is specified. Check whether client is invited in the
- list. If not, then check whether it has been invited otherwise. */
-
- } else {
- /* XXX client must be invited to be able to join the channel */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+ strncat(check, client->nickname, strlen(client->nickname));
+ if (!strchr(client->nickname, '@')) {
+ strncat(check, "@", 1);
+ strncat(check, server->server_name, strlen(server->server_name));
+ }
+ strncat(check, "!", 1);
+ strncat(check, client->username, strlen(client->username));
+ if (!strchr(client->username, '@')) {
+ strncat(check, "@", 1);
+ strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
}
}
- /* Check ban list if set */
- if (channel->mode & SILC_CHANNEL_MODE_BAN) {
+ /* Check invite list if channel is invite-only channel */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+ channel->mode & SILC_CHANNEL_MODE_INVITE && channel->invite_list) {
+ if (!silc_string_match(channel->invite_list, check)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_NOT_INVITED);
+ goto out;
+ }
+ }
+ /* Check ban list if it exists. If the client's nickname, server,
+ username and/or hostname is in the ban list the access to the
+ channel is denied. */
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
+ if (silc_string_match(channel->ban_list, check)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
+ goto out;
+ }
}
+ /* Get passphrase */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+ if (tmp) {
+ passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
+ memcpy(passphrase, tmp, tmp_len);
+ }
+
/* Check the channel passphrase if set. */
if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
- if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
- strlen(channel->mode_data.passphrase))) {
+ if (!passphrase || memcmp(channel->passphrase, passphrase,
+ strlen(channel->passphrase))) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_PASSWORD);
goto out;
/* Check user count limit if set. */
if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
if (silc_list_count(channel->user_list) + 1 >
- channel->mode_data.user_limit) {
+ channel->user_limit) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_CHANNEL_IS_FULL);
goto out;
* Client is allowed to join to the channel. Make it happen.
*/
- /* Get the client entry */
- if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
- client = (SilcClientEntry)sock->user_data;
- } else {
- client = silc_idlist_find_client_by_id(server->local_list, client_id,
- NULL);
- if (!client) {
- /* XXX actually this is useless since router finds always cell's
- local clients from its local lists. */
- client = silc_idlist_find_client_by_id(server->global_list, client_id,
- NULL);
- if (!client)
- goto out;
- }
- }
-
/* Check whether the client already is on the channel */
if (silc_server_client_on_channel(client, channel)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
channel->channel_key->cipher->name,
channel->key_len / 8, channel->key);
silc_free(tmp);
- if (!channel->topic) {
- reply =
- silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
- SILC_STATUS_OK, ident, 9,
- 2, channel->channel_name,
- strlen(channel->channel_name),
- 3, chidp->data, chidp->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, 10,
- 2, channel->channel_name,
- strlen(channel->channel_name),
- 3, chidp->data, chidp->len,
- 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);
- }
+ reply =
+ silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
+ SILC_STATUS_OK, ident, 13,
+ 2, channel->channel_name,
+ strlen(channel->channel_name),
+ 3, chidp->data, chidp->len,
+ 4, clidp->data, clidp->len,
+ 5, mode, 4,
+ 6, tmp2, 4,
+ 7, keyp->data, keyp->len,
+ 8, channel->ban_list,
+ channel->ban_list ?
+ strlen(channel->ban_list) : 0,
+ 9, channel->invite_list,
+ channel->invite_list ?
+ strlen(channel->invite_list) : 0,
+ 10, channel->topic,
+ channel->topic ?
+ strlen(channel->topic) : 0,
+ 11, channel->hmac->hmac->name,
+ strlen(channel->hmac->hmac->name),
+ 12, tmp3, 4,
+ 13, user_list->data, user_list->len,
+ 14, mode_list->data,
+ mode_list->len);
/* Send command reply */
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
}
} else {
SILC_GET32_MSB(user_limit, tmp);
- channel->mode_data.user_limit = user_limit;
+ channel->user_limit = user_limit;
}
} else {
if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
/* User limit mode is unset. Remove user limit */
- channel->mode_data.user_limit = 0;
+ channel->user_limit = 0;
}
if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
}
/* Save the passphrase */
- channel->mode_data.passphrase = strdup(tmp);
+ channel->passphrase = strdup(tmp);
}
} else {
if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
/* Passphrase mode is unset. remove the passphrase */
- if (channel->mode_data.passphrase) {
- silc_free(channel->mode_data.passphrase);
- channel->mode_data.passphrase = NULL;
- }
- }
- }
-
- if (mode_mask & SILC_CHANNEL_MODE_BAN) {
- if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
- /* Ban list is specified for channel */
-
- /* Get ban list */
- tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
- }
-
- /* XXX check that channel founder is not banned */
-
- /* Save the ban list */
- channel->mode_data.ban_list = strdup(tmp);
- }
- } else {
- if (channel->mode & SILC_CHANNEL_MODE_BAN) {
- /* Ban mode is unset. Remove the entire ban list */
- if (channel->mode_data.ban_list) {
- silc_free(channel->mode_data.ban_list);
- channel->mode_data.ban_list = NULL;
- }
- }
- }
-
- if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
- if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
- /* Invite list is specified for channel */
-
- /* Get invite list */
- tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- goto out;
- }
-
- /* Save the invite linst */
- channel->mode_data.invite_list = strdup(tmp);
- }
- } else {
- if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
- /* Invite list mode is unset. Remove the entire invite list */
- if (channel->mode_data.invite_list) {
- silc_free(channel->mode_data.invite_list);
- channel->mode_data.invite_list = NULL;
+ if (channel->passphrase) {
+ silc_free(channel->passphrase);
+ channel->passphrase = NULL;
}
}
}
if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
/* Cipher mode is unset. Remove the cipher and revert back to
default cipher */
-
- if (channel->mode_data.cipher) {
- silc_free(channel->mode_data.cipher);
- channel->mode_data.cipher = NULL;
- channel->mode_data.key_len = 0;
- }
+ char *cipher = channel->channel_key->cipher->name;
/* Generate new cipher and key for the channel */
/* Delete old cipher and allocate default one */
silc_cipher_free(channel->channel_key);
- if (!channel->cipher)
- silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
- else {
- if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
- SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
- goto out;
- }
+ if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+ SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
+ goto out;
}
/* Re-generate channel key */
out:
silc_server_command_free(cmd);
}
+
+/* Server side of command BAN. This is used to manage the ban list of the
+ channel. To add clients and remove clients from the ban list. */
+
+SILC_SERVER_CMD_FUNC(ban)
+{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ SilcServer server = cmd->server;
+ SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcBuffer packet;
+ SilcChannelEntry channel;
+ SilcChannelClientEntry chl;
+ SilcChannelID *channel_id = NULL;
+ unsigned char *id, *add, *del;
+ unsigned int id_len, tmp_len;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
+
+ if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+ goto out;
+
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
+
+ /* Get Channel ID */
+ id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+ if (id) {
+ channel_id = silc_id_payload_parse_id(id, id_len);
+ if (!channel_id) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NO_CHANNEL_ID);
+ goto out;
+ }
+ }
+
+ /* Get channel entry. The server must know about the channel since the
+ client is expected to be on the channel. */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+ goto out;
+ }
+ }
+
+ /* Check whether this client is on the channel */
+ if (!silc_server_client_on_channel(client, channel)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NOT_ON_CHANNEL);
+ goto out;
+ }
+
+ /* Get entry to the channel user list */
+ silc_list_start(channel->user_list);
+ while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+ if (chl->client == client)
+ break;
+
+ /* The client must be at least channel operator. */
+ if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+ goto out;
+ }
+
+ /* Get the new ban and add it to the ban list */
+ add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+ if (add) {
+ if (!channel->ban_list)
+ channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
+ else
+ channel->ban_list = silc_realloc(channel->ban_list,
+ sizeof(*channel->ban_list) *
+ (tmp_len +
+ strlen(channel->ban_list) + 2));
+ strncat(channel->ban_list, add, tmp_len);
+ strncat(channel->ban_list, ",", 1);
+ }
+
+ /* Get the ban to be removed and remove it from the list */
+ del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+ if (del && channel->ban_list) {
+ char *start, *end, *n;
+
+ if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
+ silc_free(channel->ban_list);
+ channel->ban_list = NULL;
+ goto out0;
+ }
+
+ start = strstr(channel->ban_list, del);
+ if (start && strlen(start) >= tmp_len) {
+ end = start + tmp_len;
+ n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
+ strncat(n, channel->ban_list, start - channel->ban_list);
+ strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
+ end) - 1);
+ silc_free(channel->ban_list);
+ channel->ban_list = n;
+ }
+ }
+
+ out0:
+
+ /* Send the BAN notify type to our primary router. */
+ if (!server->standalone && (add || del))
+ silc_server_send_notify_ban(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel, add, del);
+
+ /* Send the reply back to the client */
+ if (channel->ban_list)
+ packet =
+ silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+ SILC_STATUS_OK, ident, 2,
+ 2, id, id_len,
+ 3, channel->ban_list,
+ strlen(channel->ban_list) - 1);
+ else
+ packet =
+ silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+ SILC_STATUS_OK, ident, 1,
+ 2, id, id_len);
+
+ silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
+ packet->data, packet->len, FALSE);
+
+ silc_buffer_free(packet);
+
+ out:
+ if (channel_id)
+ silc_free(channel_id);
+ silc_server_command_free(cmd);
+}
SILC_SERVER_CMD_FUNC(silcoper);
SILC_SERVER_CMD_FUNC(leave);
SILC_SERVER_CMD_FUNC(users);
+SILC_SERVER_CMD_FUNC(ban);
#endif
silc_free(id);
}
+ /* Get the ban list */
+ tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
+ if (tmp) {
+ if (entry->ban_list)
+ silc_free(entry->ban_list);
+ entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
+ memcpy(entry->ban_list, tmp, len);
+ }
+
+ /* Get the invite list */
+ tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
+ if (tmp) {
+ if (entry->invite_list)
+ silc_free(entry->invite_list);
+ entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
+ memcpy(entry->invite_list, tmp, len);
+ }
+
+ /* Get the topic */
+ tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
+ if (tmp) {
+ if (entry->topic)
+ silc_free(entry->topic);
+ entry->topic = strdup(tmp);
+ }
+
/* If channel was not created we know there is global users on the
channel. */
entry->global_users = (created == 0 ? TRUE : FALSE);
char username
- Client's (meaning user's) real name. This is defined in following
- manner:
+ Client's usename. This is defined in the following manner:
Server type List type Contents
====================================================
char *topic;
char *cipher;
- /* Data that is related to different channel modes. */
- struct {
- unsigned int user_limit;
- unsigned char *passphrase;
- unsigned char *ban_list;
- unsigned char *invite_list;
- unsigned char *cipher;
- unsigned int key_len;
- } mode_data;
+ unsigned int user_limit;
+ unsigned char *passphrase;
+ char *invite_list;
+ char *ban_list;
/* List of users on channel */
SilcList user_list;
break;
+ case SILC_NOTIFY_TYPE_BAN:
+ /*
+ * Save the ban
+ */
+
+ SILC_LOG_DEBUG(("BAN notify"));
+
+ /* Get Channel ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_free(channel_id);
+ goto out;
+ }
+ }
+ silc_free(channel_id);
+
+ /* Get the new ban and add it to the ban list */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (tmp) {
+ if (!channel->ban_list)
+ channel->ban_list = silc_calloc(tmp_len + 2,
+ sizeof(*channel->ban_list));
+ else
+ channel->ban_list = silc_realloc(channel->ban_list,
+ sizeof(*channel->ban_list) *
+ (tmp_len +
+ strlen(channel->ban_list) + 2));
+ strncat(channel->ban_list, tmp, tmp_len);
+ strncat(channel->ban_list, ",", 1);
+ }
+
+ /* Get the ban to be removed and remove it from the list */
+ tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (tmp && channel->ban_list) {
+ char *start, *end, *n;
+
+ if (!strcmp(channel->ban_list, tmp)) {
+ silc_free(channel->ban_list);
+ channel->ban_list = NULL;
+ break;
+ }
+
+ start = strstr(channel->ban_list, tmp);
+ if (start && strlen(start) >= tmp_len) {
+ end = start + tmp_len;
+ n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
+ strncat(n, channel->ban_list, start - channel->ban_list);
+ strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
+ end) - 1);
+ silc_free(channel->ban_list);
+ channel->ban_list = n;
+ }
+ }
+
+ break;
+
/* Ignore rest of the notify types for now */
case SILC_NOTIFY_TYPE_NONE:
case SILC_NOTIFY_TYPE_MOTD:
silc_buffer_free(idp);
}
+/* Sends BAN notify type. This tells that `ban' has been either `add'ed
+ or `del'eted on the `channel. This function is used to send the packet
+ between routers as broadcast packet. */
+
+void silc_server_send_notify_ban(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ SilcChannelEntry channel,
+ char *add, char *del)
+{
+ SilcBuffer idp;
+
+ idp = silc_id_payload_encode((void *)channel->id, SILC_ID_CHANNEL);
+ silc_server_send_notify(server, sock, broadcast,
+ SILC_NOTIFY_TYPE_BAN, 3,
+ idp->data, idp->len,
+ add, add ? strlen(add) : 0,
+ del, del ? strlen(del) : 0);
+ silc_buffer_free(idp);
+}
+
/* Sends notify message destined to specific entity. */
void silc_server_send_notify_dest(SilcServer server,
SilcClientID *client_id,
unsigned int client_id_len,
unsigned int mode_mask);
+void silc_server_send_notify_ban(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ SilcChannelEntry channel,
+ char *add, char *del);
void silc_server_send_notify_dest(SilcServer server,
SilcSocketConnection sock,
int broadcast,
[Cipher]
-rc6:../lib/silcsim/modules/rc6.sim.so:16:16
-twofish:../lib/silcsim/modules/twofish.sim.so:16:16
-mars:../lib/silcsim/modules/mars.sim.so:16:16
+aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16
+aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
+aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
+twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
+twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
+twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
+mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
+mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
+mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16
none:../lib/silcsim/modules/none.sim.so:0:0
-[Hash]
+[Hash]
md5::64:16
sha1::64:20
[hmac]
hmac-sha1-96:sha1:12
hmac-md5-96:md5:12
-hmac-sha1:sha1:20
+hmac-sha1:sha1:20
hmac-md5:md5:16
#[PKCS]
Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
[ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
[ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.42.253:212.146.42.253:1334
[Logging]
infologfile:silcd2.log:10000
:::1336:1
[AdminConnection]
-*:silc:silc:passwd:testi
+*:priikone:*:passwd:testi
[ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.42.253:passwd:priikone:1333:1:1
[RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.42.253:passwd:priikone:1335:1:1:0
[DenyConnection]
[RedirectClient]
-
-[motd]
-./motd
7 SILC_COMMAND_INVITE
Max Arguments: 4
- Arguments: (1) [<Client ID>] (2) [<Channel ID>]
+ Arguments: (1) [<Client ID>] (2) <Channel ID>
(3) [<adding client>] (4) [<removing client>]
This command is used to invite other clients to join to the
nickname and hostname and add to the invite list before sending
the notify packet.
- When this command is given without any arguments then the command
- merely returns the invite list of the channel. This command must
- fail if the requested channel does not exist, the requested
- <Client ID> is already on the channel or if the channel is invite
- only channel and the caller of this command does not have at least
- channel operator privileges.
+ When this command is given with only <Channel ID> argument then
+ the command merely returns the invite list of the channel. This
+ command must fail if the requested channel does not exist, the
+ requested <Client ID> is already on the channel or if the channel
+ is invite only channel and the caller of this command does not
+ have at least channel operator privileges.
Reply messages to the command:
Arguments: (1) <Status Payload> (2) <channel>
(3) <Channel ID> (4) <Client ID>
(5) <channel mode mask> (6) <created>
- (7) <Channel Key Payload> (8) [<ban mask>]
+ (7) <Channel Key Payload> (8) [<ban list>]
(9) [<invite list>] (10) [<topic>]
(11) [<hmac>] (12) <list count>
(13) <Client ID list> (14) <client mode list>
26 SILC_COMMAND_BAN
Max Arguments: 3
- Arguments: (1) [<Channel ID>] (2) [<adding client>]
+ Arguments: (1) <Channel ID> (2) [<adding client>]
(3) [<removing client>]
This command is used to manage the ban list of the channel
from than one clients then the lists are an comma (`,') separated
list.
- If this command is executed without any arguments the command
+ If this command is executed without the ban arguments the command
merely replies with the current ban list.
SILC_STATUS_ERR_NOT_REGISTERED
SILC_STATUS_ERR_TOO_MANY_PARAMS
SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID
+ SILC_STATUS_ERR_NO_CHANNEL_ID
SILC_STATUS_ERR_NOT_ON_CHANNEL
SILC_STATUS_ERR_NO_CHANNEL_PRIV
SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 3),
SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", SILC_CF_LAG | SILC_CF_REG, 2),
SILC_CLIENT_CMD(users, USERS, "USERS", SILC_CF_LAG | SILC_CF_REG, 2),
+ SILC_CLIENT_CMD(ban, BAN, "BAN", SILC_CF_LAG | SILC_CF_REG, 3),
{ NULL, 0, NULL, 0, 0 },
};
mode &= ~SILC_CHANNEL_MODE_PASSPHRASE;
}
break;
- case 'b':
- if (add) {
- mode |= SILC_CHANNEL_MODE_BAN;
- type = 5;
- arg = cmd->argv[3];
- arg_len = cmd->argv_lens[3];
- } else {
- mode &= ~SILC_CHANNEL_MODE_BAN;
- }
- break;
- case 'I':
- if (add) {
- mode |= SILC_CHANNEL_MODE_INVITE_LIST;
- type = 6;
- arg = cmd->argv[3];
- arg_len = cmd->argv_lens[3];
- } else {
- mode &= ~SILC_CHANNEL_MODE_INVITE_LIST;
- }
- break;
case 'c':
if (add) {
mode |= SILC_CHANNEL_MODE_CIPHER;
out:
silc_client_command_free(cmd);
}
+
+/* Command BAN. This is used to manage the ban list of the channel. */
+
+SILC_CLIENT_CMD_FUNC(ban)
+{
+ SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+ SilcClientConnection conn = cmd->conn;
+ SilcChannelEntry channel;
+ SilcBuffer buffer, chidp;
+ int type = 0;
+ char *name, *ban = NULL;
+
+ if (!cmd->conn) {
+ SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+ COMMAND_ERROR;
+ goto out;
+ }
+
+ if (cmd->argc < 2) {
+ cmd->client->ops->say(cmd->client, conn,
+ "Usage: /BAN <channel> "
+ "[+|-[<nickname>[@<server>[!<username>[@hostname>]]]]]");
+ COMMAND_ERROR;
+ goto out;
+ }
+
+ if (cmd->argv[1][0] == '*') {
+ if (!conn->current_channel) {
+ cmd->client->ops->say(cmd->client, conn, "You are not on any channel");
+ COMMAND_ERROR;
+ goto out;
+ }
+
+ channel = conn->current_channel;
+ } else {
+ name = cmd->argv[1];
+
+ channel = silc_client_get_channel(cmd->client, conn, name);
+ if (!channel) {
+ cmd->client->ops->say(cmd->client, conn, "You are on that channel");
+ COMMAND_ERROR;
+ goto out;
+ }
+ }
+
+ if (cmd->argc == 3) {
+ if (cmd->argv[2][0] == '+')
+ type = 2;
+ else
+ type = 3;
+
+ ban = cmd->argv[2];
+ ban++;
+ }
+
+ chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+
+ /* Send the command */
+ if (ban)
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 2,
+ 1, chidp->data, chidp->len,
+ type, ban, strlen(ban));
+ else
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 1,
+ 1, chidp->data, chidp->len);
+
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ 0, NULL, NULL, buffer->data, buffer->len, TRUE);
+ silc_buffer_free(buffer);
+ silc_buffer_free(chidp);
+
+ /* Notify application */
+ COMMAND;
+
+ out:
+ silc_client_command_free(cmd);
+}
SILC_CLIENT_CMD_FUNC(silcoper);
SILC_CLIENT_CMD_FUNC(leave);
SILC_CLIENT_CMD_FUNC(users);
+SILC_CLIENT_CMD_FUNC(ban);
#endif
SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER),
SILC_CLIENT_CMD_REPLY(leave, LEAVE),
SILC_CLIENT_CMD_REPLY(users, USERS),
+ SILC_CLIENT_CMD_REPLY(ban, BAN),
{ NULL, 0 },
};
if (!channel_id)
goto out;
- /* Get the channel name */
+ /* Get the channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
SILC_ID_CHANNEL, &id_cache)) {
silc_free(channel_id);
SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
silc_client_command_reply_free(cmd);
}
+
+SILC_CLIENT_CMD_REPLY_FUNC(ban)
+{
+ SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+ SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+ SilcCommandStatus status;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcChannelEntry channel;
+ SilcChannelID *channel_id;
+ unsigned char *tmp;
+ unsigned int len;
+
+ tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
+ SILC_GET16_MSB(status, tmp);
+ if (status != SILC_STATUS_OK) {
+ cmd->client->ops->say(cmd->client, conn,
+ "%s", silc_client_command_status_message(status));
+ COMMAND_REPLY_ERROR;
+ goto out;
+ }
+
+ /* Take Channel ID */
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+ if (!tmp)
+ goto out;
+
+ channel_id = silc_id_payload_parse_id(tmp, len);
+ if (!channel_id)
+ goto out;
+
+ /* Get the channel entry */
+ if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
+ SILC_ID_CHANNEL, &id_cache)) {
+ silc_free(channel_id);
+ COMMAND_REPLY_ERROR;
+ goto out;
+ }
+
+ channel = (SilcChannelEntry)id_cache->context;
+
+ /* Get the ban list */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+
+ /* Notify application */
+ COMMAND_REPLY((ARGS, channel, tmp));
+
+ /* Execute any pending command callbacks */
+ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN);
+
+ out:
+ SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_BAN);
+ silc_client_command_reply_free(cmd);
+}
SILC_CLIENT_CMD_REPLY_FUNC(silcoper);
SILC_CLIENT_CMD_REPLY_FUNC(leave);
SILC_CLIENT_CMD_REPLY_FUNC(users);
+SILC_CLIENT_CMD_REPLY_FUNC(ban);
#endif
unsigned int x_len;
unsigned int x_type;
SilcBuffer buffer;
- int i;
+ int i, k;
va_start(ap, argc);
argv_lens = silc_calloc(argc, sizeof(unsigned int));
argv_types = silc_calloc(argc, sizeof(unsigned int));
- for (i = 0; i < argc; i++) {
+ for (i = 0, k = 0; i < argc; i++) {
x_type = va_arg(ap, unsigned int);
x = va_arg(ap, unsigned char *);
x_len = va_arg(ap, unsigned int);
- argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
- memcpy(argv[i], x, x_len);
- argv_lens[i] = x_len;
- argv_types[i] = x_type;
+ if (!x_type || !x || !x_len)
+ continue;
+
+ argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+ memcpy(argv[k], x, x_len);
+ argv_lens[k] = x_len;
+ argv_types[k] = x_type;
+ k++;
}
- buffer = silc_command_payload_encode(cmd, argc, argv,
- argv_lens, argv_types, ident);
+ buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
+ argv_types, ident);
- for (i = 0; i < argc; i++)
+ for (i = 0; i < k; i++)
silc_free(argv[i]);
silc_free(argv);
silc_free(argv_lens);
unsigned int x_len;
unsigned int x_type;
SilcBuffer buffer;
- int i;
+ int i, k;
argv = silc_calloc(argc, sizeof(unsigned char *));
argv_lens = silc_calloc(argc, sizeof(unsigned int));
argv_types = silc_calloc(argc, sizeof(unsigned int));
- for (i = 0; i < argc; i++) {
+ for (i = 0, k = 0; i < argc; i++) {
x_type = va_arg(ap, unsigned int);
x = va_arg(ap, unsigned char *);
x_len = va_arg(ap, unsigned int);
- argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
- memcpy(argv[i], x, x_len);
- argv_lens[i] = x_len;
- argv_types[i] = x_type;
+ if (!x_type || !x || !x_len)
+ continue;
+
+ argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+ memcpy(argv[k], x, x_len);
+ argv_lens[k] = x_len;
+ argv_types[k] = x_type;
+ k++;
}
- buffer = silc_command_payload_encode(cmd, argc, argv,
- argv_lens, argv_types, ident);
+ buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
+ argv_types, ident);
- for (i = 0; i < argc; i++)
+ for (i = 0; i < k; i++)
silc_free(argv[i]);
silc_free(argv);
silc_free(argv_lens);
unsigned int x_len;
unsigned int x_type;
SilcBuffer buffer;
- int i;
+ int i, k;
va_start(ap, argc);
argv_lens[0] = sizeof(status_data);
argv_types[0] = 1;
- for (i = 1; i < argc; i++) {
+ for (i = 1, k = 1; i < argc; i++) {
x_type = va_arg(ap, unsigned int);
x = va_arg(ap, unsigned char *);
x_len = va_arg(ap, unsigned int);
- argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
- memcpy(argv[i], x, x_len);
- argv_lens[i] = x_len;
- argv_types[i] = x_type;
+ if (!x_type || !x || !x_len)
+ continue;
+
+ argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+ memcpy(argv[k], x, x_len);
+ argv_lens[k] = x_len;
+ argv_types[k] = x_type;
+ k++;
}
- buffer = silc_command_payload_encode(cmd, argc, argv,
- argv_lens, argv_types, ident);
+ buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,
+ argv_types, ident);
- for (i = 0; i < argc; i++)
+ for (i = 0; i < k; i++)
silc_free(argv[i]);
silc_free(argv);
silc_free(argv_lens);
unsigned int *argv_lens = NULL, *argv_types = NULL;
unsigned char *x;
unsigned int x_len;
- int i, len = 0;
+ int i, k, len = 0;
if (argc) {
argv = silc_calloc(argc, sizeof(unsigned char *));
argv_lens = silc_calloc(argc, sizeof(unsigned int));
argv_types = silc_calloc(argc, sizeof(unsigned int));
- for (i = 0; i < argc; i++) {
+ for (i = 0, k = 0; i < argc; i++) {
x = va_arg(ap, unsigned char *);
x_len = va_arg(ap, unsigned int);
+
+ if (!x || !x_len)
+ continue;
- argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
- memcpy(argv[i], x, x_len);
- argv_lens[i] = x_len;
- argv_types[i] = i + 1;
+ argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+ memcpy(argv[k], x, x_len);
+ argv_lens[k] = x_len;
+ argv_types[k] = i + 1;
+ k++;
}
- args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
+ args = silc_argument_payload_encode(k, argv, argv_lens, argv_types);
len = args->len;
- for (i = 0; i < argc; i++)
+ for (i = 0; i < k; i++)
silc_free(argv[i]);
silc_free(argv);
silc_free(argv_lens);
silc_buffer_format(buffer,
SILC_STR_UI_SHORT(type),
SILC_STR_UI_SHORT(len),
- SILC_STR_UI_CHAR(argc),
+ SILC_STR_UI_CHAR(k),
SILC_STR_END);
- if (argc) {
+ if (k) {
silc_buffer_pull(buffer, 5);
silc_buffer_format(buffer,
SILC_STR_UI_XNSTRING(args->data, args->len),
}
/* Inspects the `string' for wildcards and returns regex string that can
- be used by the GNU regex library. This has a lot overhead but luckily
- this is used only for short strings. */
+ be used by the GNU regex library. A comma (`,') in the `string' means
+ that the string is list. */
char *silc_string_regexify(const char *string)
{
int i, len, count;
char *regex;
- /* If there is no wildcards then we don't need to regexify the string. */
- if (!strchr(string, '*') && !strchr(string, '?'))
- return strdup(string);
-
len = strlen(string);
- count = 0;
-
+ count = 4;
for (i = 0; i < len; i++)
if (string[i] == '*' || string[i] == '?')
count++;
- regex = silc_calloc(len + count + 4, sizeof(*regex));
+ regex = silc_calloc(len + count, sizeof(*regex));
count = 0;
regex[count] = '(';
if (string[i] == '*' || string[i] == '?') {
regex[count] = '.';
count++;
+ } else if (string[i] == ',') {
+ regex[count] = '|';
+ count++;
+ continue;
}
regex[count] = string[i];
len2 = strlen(string2);
tmp = silc_calloc(2 + len1 + len2, sizeof(*tmp));
- memcpy(tmp, string1, len1 - 2);
- memcpy(tmp, "|", 1);
- memcpy(tmp, string2 + 1, len2 - 1);
+ strncat(tmp, string1, len1 - 2);
+ strncat(tmp, "|", 1);
+ strncat(tmp, string2 + 1, len2 - 1);
return tmp;
}
return ret;
}
+
+/* Do regex match to the two strings `string1' and `string2'. If the
+ `string2' matches the `string1' this returns TRUE. */
+
+int silc_string_match(const char *string1, const char *string2)
+{
+ char *s1;
+ int ret = FALSE;
+
+ s1 = silc_string_regexify(string1);
+ ret = silc_string_regex_match(s1, string2);
+ silc_free(s1);
+
+ return ret;
+}
int silc_string_compare(char *string1, char *string2);
char *silc_string_regexify(const char *string);
int silc_string_regex_match(const char *regex, const char *string);
+int silc_string_match(const char *string1, const char *string2);
#endif