From f4502217007852082bc93d144551f576bc9f5428 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 14 Mar 2001 19:38:18 +0000 Subject: [PATCH] updates. --- CHANGES | 11 ++ apps/silcd/command.c | 146 ++++++++++---------------- apps/silcd/idlist.h | 7 ++ doc/draft-riikonen-silc-spec-01.nroff | 8 +- lib/silccore/silccommand.h | 13 ++- 5 files changed, 91 insertions(+), 94 deletions(-) diff --git a/CHANGES b/CHANGES index 03d80a67..9333281e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,14 @@ +Wed Mar 14 20:37:35 EET 2001 Pekka Riikonen + + * Added new SILC_CF_LAG_STRICT command flag that strictly forces + that the command may be executed only once in (about) 2 seconds. + The old SILC_CF_LAG flag is same but allows command bursts up + to five before limiting. + + Added the support for CF_LAG and CF_LAG_STRICT flags to the + server code. Various commands now includes the CF_LAG_STRICT + flag to disallow any kind of miss-use of the command. + Wed Mar 14 16:10:30 EET 2001 Pekka Riikonen * Changed the format of AdminConnection configuration section diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 9f0866a5..6792f3c0 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -45,23 +45,23 @@ SilcServerCommand silc_command_list[] = SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG), + SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), + SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(connect, CONNECT, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), - SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(restart, RESTART, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(close, CLOSE, @@ -70,7 +70,7 @@ SilcServerCommand silc_command_list[] = SILC_CF_OPER), SILC_SERVER_CMD(silcoper, SILCOPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER), - SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG), { NULL, 0 }, @@ -116,9 +116,8 @@ static int silc_server_is_registered(SilcServer server, /* Internal context to hold data when executed command with timeout. */ typedef struct { - SilcServer server; - SilcSocketConnection sock; - SilcPacketContext *packet; + SilcServerCommandContext ctx; + SilcServerCommand *cmd; } *SilcServerCommandTimeout; /* Timeout callback to process commands with timeout for client. Client's @@ -127,67 +126,61 @@ typedef struct { SILC_TASK_CALLBACK(silc_server_command_process_timeout) { SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context; - SilcServerCommandContext ctx; - SilcServerCommand *cmd; - SilcClientEntry client = (SilcClientEntry)timeout->sock->user_data; + SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data; /* Update access time */ client->last_command = time(NULL); + if (!(timeout->cmd->flags & SILC_CF_REG)) + timeout->cmd->cb(timeout->ctx); + else if (silc_server_is_registered(timeout->ctx->server, + timeout->ctx->sock, + timeout->ctx, + timeout->cmd->cmd)) + timeout->cmd->cb(timeout->ctx); + + silc_free(timeout); +} + +/* Processes received command packet. */ + +void silc_server_command_process(SilcServer server, + SilcSocketConnection sock, + SilcPacketContext *packet) +{ + SilcServerCommandContext ctx; + SilcServerCommand *cmd; + /* Allocate command context. This must be free'd by the command routine receiving it. */ ctx = silc_server_command_alloc(); - ctx->server = timeout->server; - ctx->sock = timeout->sock; - ctx->packet = timeout->packet; - + ctx->server = server; + ctx->sock = silc_socket_dup(sock); + ctx->packet = silc_packet_context_dup(packet); /* Save original packet */ + /* Parse the command payload in the packet */ - ctx->payload = silc_command_payload_parse(ctx->packet->buffer); + ctx->payload = silc_command_payload_parse(packet->buffer); if (!ctx->payload) { SILC_LOG_ERROR(("Bad command payload, packet dropped")); - silc_buffer_free(ctx->packet->buffer); + silc_buffer_free(packet->buffer); + silc_packet_context_free(packet); silc_socket_free(ctx->sock); - silc_packet_context_free(ctx->packet); silc_free(ctx); - silc_free(timeout); return; } ctx->args = silc_command_get_args(ctx->payload); - /* Execute command. If this fails the packet is dropped. */ + /* Get the command */ for (cmd = silc_command_list; cmd->cb; cmd++) - if (cmd->cmd == silc_command_get(ctx->payload)) { - - if (!(cmd->flags & SILC_CF_REG)) { - cmd->cb(ctx); - break; - } - - if (silc_server_is_registered(ctx->server, ctx->sock, ctx, cmd->cmd)) { - cmd->cb(ctx); - break; - } - } + if (cmd->cmd == silc_command_get(ctx->payload)) + break; if (cmd == NULL) { SILC_LOG_ERROR(("Unknown command, packet dropped")); silc_server_command_free(ctx); - silc_free(timeout); return; } - silc_free(timeout); -} - -/* Processes received command packet. */ - -void silc_server_command_process(SilcServer server, - SilcSocketConnection sock, - SilcPacketContext *packet) -{ - SilcServerCommandContext ctx; - SilcServerCommand *cmd; - /* Execute client's commands always with timeout. Normally they are executed with zero (0) timeout but if client is sending command more frequently than once in 2 seconds, then the timeout may be 0 to 2 @@ -195,12 +188,22 @@ void silc_server_command_process(SilcServer server, if (sock->type == SILC_SOCKET_TYPE_CLIENT) { SilcClientEntry client = (SilcClientEntry)sock->user_data; SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout)); + int fast; - timeout->server = server; - timeout->sock = silc_socket_dup(sock); - timeout->packet = silc_packet_context_dup(packet); + timeout->ctx = ctx; + timeout->cmd = cmd; - if (client->last_command && (time(NULL) - client->last_command) < 2) + if (client->last_command && (time(NULL) - client->last_command) < 2) { + client->fast_command++; + fast = FALSE; + } else { + client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : + client->fast_command--); + fast = TRUE; + } + + if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) || + (client->fast_command > 5 && cmd->flags & SILC_CF_LAG))) silc_task_register(server->timeout_queue, sock->sock, silc_server_command_process_timeout, (void *)timeout, @@ -217,45 +220,12 @@ void silc_server_command_process(SilcServer server, return; } - /* Allocate command context. This must be free'd by the - command routine receiving it. */ - ctx = silc_server_command_alloc(); - ctx->server = server; - ctx->sock = silc_socket_dup(sock); - ctx->packet = silc_packet_context_dup(packet); /* Save original packet */ - - /* Parse the command payload in the packet */ - ctx->payload = silc_command_payload_parse(packet->buffer); - if (!ctx->payload) { - SILC_LOG_ERROR(("Bad command payload, packet dropped")); - silc_buffer_free(packet->buffer); - silc_packet_context_free(packet); - silc_socket_free(ctx->sock); - silc_free(ctx); - return; - } - ctx->args = silc_command_get_args(ctx->payload); - - /* Execute command. If this fails the packet is dropped. */ - for (cmd = silc_command_list; cmd->cb; cmd++) - if (cmd->cmd == silc_command_get(ctx->payload)) { - - if (!(cmd->flags & SILC_CF_REG)) { - cmd->cb(ctx); - break; - } - - if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) { - cmd->cb(ctx); - break; - } - } + /* Execute for server */ - if (cmd == NULL) { - SILC_LOG_ERROR(("Unknown command, packet dropped")); - silc_server_command_free(ctx); - return; - } + if (!(cmd->flags & SILC_CF_REG)) + cmd->cb(ctx); + else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) + cmd->cb(ctx); } /* Allocate Command Context */ diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index e05bcbda..9d29d74f 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -241,6 +241,12 @@ typedef struct SilcChannelClientEntryStruct { not allow any command to be exeucted more than once in about 2 seconds. This is result of normal time(). + char fast_command + + Counter to check command bursts. By default, up to 5 commands + are allowed before limiting the execution. See command flags + for more detail. + SilcServerEntry router This is a pointer to the server list. This is the router server whose @@ -270,6 +276,7 @@ struct SilcClientEntryStruct { int mode; long last_command; + char fast_command; /* Pointer to the router */ SilcServerEntry router; diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index f36990e4..fa590917 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -847,8 +847,12 @@ however, choose ignore the command reply, but should not. It is expected that some of the commands may be miss-used by clients resulting various problems on the server side. Every implementation should assure that commands may not be executed more than once, say, -in two (2) seconds. This should be sufficient to prevent the miss-use -of commands. +in two (2) seconds. However, to keep response rate up, allowing for +example five (5) commands before limiting is allowed. It is recommended +that commands such as SILC_COMMAND_NICK, SILC_COMMAND_JOIN and +SILC_COMMAND_LEAVE should be limited in all cases as they require +heavy operations. This should be sufficient to prevent the miss-use of +commands. SILC commands are described in section 5 SILC Commands. diff --git a/lib/silccore/silccommand.h b/lib/silccore/silccommand.h index ec34d834..dd20052d 100644 --- a/lib/silccore/silccommand.h +++ b/lib/silccore/silccommand.h @@ -36,19 +36,24 @@ typedef struct SilcCommandPayloadStruct *SilcCommandPayload; typedef enum { SILC_CF_NONE = 0, - /* Command may only be used once per (about) 2 seconds */ + /* Command may only be used once per (about) 2 seconds. Bursts up + to 5 commands are allowed though. */ SILC_CF_LAG = (1L << 1), + /* Command may only be used once per (about) 2 seconds. No bursts + are allowed at all. */ + SILC_CF_LAG_STRICT = (1L << 2), + /* Command is available for registered connections (connections whose ID has been created. */ - SILC_CF_REG = (1L << 2), + SILC_CF_REG = (1L << 3), /* Command is available only for server operators */ - SILC_CF_OPER = (1L << 3), + SILC_CF_OPER = (1L << 4), /* Command is available only for SILC (router) operators. If this is set SILC_CF_OPER is not necessary to be set. */ - SILC_CF_SILC_OPER = (1L << 4), + SILC_CF_SILC_OPER = (1L << 5), } SilcCommandFlag; -- 2.24.0