From: Pekka Riikonen Date: Sun, 25 Mar 2001 13:23:06 +0000 (+0000) Subject: updates. X-Git-Tag: 1.2.beta1~2425 X-Git-Url: http://git.silcnet.org/gitweb/?p=runtime.git;a=commitdiff_plain;h=0bf38ae7a8125a1586d617f5f835329d1f924721 updates. --- diff --git a/CHANGES b/CHANGES index c6c440a7..c835fdbe 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,39 @@ +Sun Mar 25 13:52:51 EEST 2001 Pekka Riikonen + + * 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 + + * 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 + + * 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 * Redefined the INVITE command. The same command can be used to diff --git a/README b/README index ac9e349f..215f04f9 100644 --- a/README +++ b/README @@ -86,12 +86,7 @@ SILC Commands l Set/unset channel's user limit a Set/unset passphrase for channel that must be provided when joining to the channel. - b - Add client to/remove client from ban list - I - Add client to/remove client from invite list - c - Set/unset channel's cipher + c 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 diff --git a/apps/silc/client_ops.c b/apps/silc/client_ops.c index 690584b8..e71e8ac9 100644 --- a/apps/silc/client_ops.c +++ b/apps/silc/client_ops.c @@ -712,8 +712,30 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn, 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; } } diff --git a/apps/silcd/command.c b/apps/silcd/command.c index f92e8a39..7bfbc62d 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -72,6 +72,7 @@ SilcServerCommand silc_command_list[] = 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 }, }; @@ -2569,43 +2570,73 @@ static void silc_server_command_join_channel(SilcServer server, 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; @@ -2615,7 +2646,7 @@ static void silc_server_command_join_channel(SilcServer server, /* 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; @@ -2626,22 +2657,6 @@ static void silc_server_command_join_channel(SilcServer server, * 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, @@ -2689,39 +2704,31 @@ static void silc_server_command_join_channel(SilcServer server, 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, @@ -3338,12 +3345,12 @@ SILC_SERVER_CMD_FUNC(cmode) } } 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) { @@ -3359,66 +3366,14 @@ SILC_SERVER_CMD_FUNC(cmode) } /* 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; } } } @@ -3481,12 +3436,7 @@ SILC_SERVER_CMD_FUNC(cmode) 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 */ @@ -3494,14 +3444,10 @@ SILC_SERVER_CMD_FUNC(cmode) /* 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 */ @@ -4422,3 +4368,139 @@ SILC_SERVER_CMD_FUNC(users) 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); +} diff --git a/apps/silcd/command.h b/apps/silcd/command.h index 8fc42e1e..f8b7a5fe 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -154,5 +154,6 @@ SILC_SERVER_CMD_FUNC(shutdown); SILC_SERVER_CMD_FUNC(silcoper); SILC_SERVER_CMD_FUNC(leave); SILC_SERVER_CMD_FUNC(users); +SILC_SERVER_CMD_FUNC(ban); #endif diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index b693e2f3..37c2838d 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -724,6 +724,32 @@ SILC_SERVER_CMD_REPLY_FUNC(join) 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); diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index efca0dbf..1198e58a 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -211,8 +211,7 @@ typedef struct SilcChannelClientEntryStruct { 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 ==================================================== @@ -390,15 +389,10 @@ struct SilcChannelEntryStruct { 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; diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 16e9fa43..a938e53c 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -663,6 +663,74 @@ void silc_server_notify(SilcServer server, 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: diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 7cd17679..2dba70f3 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -1125,6 +1125,27 @@ void silc_server_send_notify_umode(SilcServer server, 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, diff --git a/apps/silcd/packet_send.h b/apps/silcd/packet_send.h index 29b34928..b856e0e4 100644 --- a/apps/silcd/packet_send.h +++ b/apps/silcd/packet_send.h @@ -174,6 +174,11 @@ void silc_server_send_notify_umode(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, diff --git a/apps/silcd/testi2.conf b/apps/silcd/testi2.conf index 42ed3eae..1eaa6071 100644 --- a/apps/silcd/testi2.conf +++ b/apps/silcd/testi2.conf @@ -1,17 +1,23 @@ [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] @@ -25,10 +31,10 @@ nobody:nobody 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 @@ -47,16 +53,13 @@ errorlogfile: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 diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index 2f658288..d641e083 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -2264,7 +2264,7 @@ List of all defined commands in SILC follows. 7 SILC_COMMAND_INVITE Max Arguments: 4 - Arguments: (1) [] (2) [] + Arguments: (1) [] (2) (3) [] (4) [] This command is used to invite other clients to join to the @@ -2294,12 +2294,12 @@ List of all defined commands in SILC follows. 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 - 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 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 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: @@ -2551,7 +2551,7 @@ List of all defined commands in SILC follows. Arguments: (1) (2) (3) (4) (5) (6) - (7) (8) [] + (7) (8) [] (9) [] (10) [] (11) [] (12) (13) (14) @@ -3162,7 +3162,7 @@ List of all defined commands in SILC follows. 26 SILC_COMMAND_BAN Max Arguments: 3 - Arguments: (1) [] (2) [] + Arguments: (1) (2) [] (3) [] This command is used to manage the ban list of the channel @@ -3183,7 +3183,7 @@ List of all defined commands in SILC follows. 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. @@ -3202,6 +3202,7 @@ List of all defined commands in SILC follows. 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 diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 002363fb..1ef9975d 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -58,6 +58,7 @@ SilcClientCommand silc_command_list[] = 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 }, }; @@ -1180,26 +1181,6 @@ SILC_CLIENT_CMD_FUNC(cmode) 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; @@ -1963,3 +1944,80 @@ SILC_CLIENT_CMD_FUNC(users) 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 " + "[+|-[[@[![@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); +} diff --git a/lib/silcclient/command.h b/lib/silcclient/command.h index fad67750..64af6d8c 100644 --- a/lib/silcclient/command.h +++ b/lib/silcclient/command.h @@ -153,5 +153,6 @@ SILC_CLIENT_CMD_FUNC(shutdown); SILC_CLIENT_CMD_FUNC(silcoper); SILC_CLIENT_CMD_FUNC(leave); SILC_CLIENT_CMD_FUNC(users); +SILC_CLIENT_CMD_FUNC(ban); #endif diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 261578cf..a97b2352 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -63,6 +63,7 @@ SilcClientCommandReply silc_command_reply_list[] = 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 }, }; @@ -679,7 +680,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic) 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); @@ -1646,3 +1647,56 @@ SILC_CLIENT_CMD_REPLY_FUNC(users) 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); +} diff --git a/lib/silcclient/command_reply.h b/lib/silcclient/command_reply.h index de788130..f1ebd1c3 100644 --- a/lib/silcclient/command_reply.h +++ b/lib/silcclient/command_reply.h @@ -98,5 +98,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown); 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 diff --git a/lib/silccore/silccommand.c b/lib/silccore/silccommand.c index 3185fe30..784bd5bb 100644 --- a/lib/silccore/silccommand.c +++ b/lib/silccore/silccommand.c @@ -195,7 +195,7 @@ SilcBuffer silc_command_payload_encode_va(SilcCommand cmd, unsigned int x_len; unsigned int x_type; SilcBuffer buffer; - int i; + int i, k; va_start(ap, argc); @@ -203,21 +203,25 @@ SilcBuffer silc_command_payload_encode_va(SilcCommand cmd, 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); @@ -238,27 +242,31 @@ SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd, 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); @@ -286,7 +294,7 @@ silc_command_reply_payload_encode_va(SilcCommand cmd, unsigned int x_len; unsigned int x_type; SilcBuffer buffer; - int i; + int i, k; va_start(ap, argc); @@ -301,21 +309,25 @@ silc_command_reply_payload_encode_va(SilcCommand cmd, 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); diff --git a/lib/silccore/silcnotify.c b/lib/silccore/silcnotify.c index d1e739b1..d8f80ca2 100644 --- a/lib/silccore/silcnotify.c +++ b/lib/silccore/silcnotify.c @@ -83,27 +83,31 @@ SilcBuffer silc_notify_payload_encode(SilcNotifyType type, unsigned int argc, 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); @@ -116,10 +120,10 @@ SilcBuffer silc_notify_payload_encode(SilcNotifyType type, unsigned int argc, 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), diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index c6d9dd30..ba4b9cc7 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -602,26 +602,21 @@ int silc_string_compare(char *string1, char *string2) } /* 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] = '('; @@ -631,6 +626,10 @@ char *silc_string_regexify(const char *string) if (string[i] == '*' || string[i] == '?') { regex[count] = '.'; count++; + } else if (string[i] == ',') { + regex[count] = '|'; + count++; + continue; } regex[count] = string[i]; @@ -656,9 +655,9 @@ char *silc_string_regex_combine(const char *string1, const char *string2) 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; } @@ -680,3 +679,18 @@ int silc_string_regex_match(const char *regex, const char *string) 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; +} diff --git a/lib/silcutil/silcutil.h b/lib/silcutil/silcutil.h index d58909e0..dc619676 100644 --- a/lib/silcutil/silcutil.h +++ b/lib/silcutil/silcutil.h @@ -47,5 +47,6 @@ char *silc_id_render(void *id, unsigned short type); 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