From: Pekka Riikonen Date: Sun, 7 Apr 2002 15:31:36 +0000 (+0000) Subject: updates. X-Git-Tag: silc.client.0.8.6~4^2~21 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=f1a1c41a159700e60f98a1dcf3bc4801c36af62c updates. --- diff --git a/CHANGES b/CHANGES index fc475d70..45db30e1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,34 @@ +Sun Apr 7 17:07:59 EEST 2002 Pekka Riikonen + + * Added STATS command to the protocol after all, to return + various statistical information about the network. It can + be used by clients to retrieve statistical information, and + servers may use it to to fetch cell and network wide + statistics from router. Updated the protocol specs and + implemented it to the server. Protocol TODO #16. + Affected files are lib/silccore/silccommand, silcd/command.[ch], + silcd/command_reply.[ch]. + +Sat Apr 6 17:08:58 EEST 2002 Pekka Riikonen + + * The LIST command reply in client libary now adds new channel + entry if the returned channel doesn't exist yet in cache, + and returns the channel entry to the application in the + command_reply client operation. Affected file is + lib/silcclient/command_reply.c. + + * Changed the channel message payload's MAC generation to + include the IV in the MAC as well. This way all relevant + parts of the channel message payload are authenticated also + with the channel message MAC (and not only by packet MAC). + Causes incompatibility with 1.0 protocol. Protocol TODO #7. + Affected file is lib/silccore/silcchannel.c. + + * Fixed the SKE to save the remote version, since the + silc_ske_parse_version mistakenly checked wrong version, + after it replaced the start payload. Affected files are + lib/silcske/silcske.[ch]. + Fri Apr 5 16:03:03 EEST 2002 Pekka Riikonen * Splitted lib/silcutil/silcutil.h into silcstrutil.h for diff --git a/TODO b/TODO index 17012127..26c76605 100644 --- a/TODO +++ b/TODO @@ -135,26 +135,15 @@ describe new stuff to be added to protocol versions 1.x. new features without always making the command incompatible to previous version. To be included in protocol version 1.1. - 5. Inviting and banning by public key should be made possible. To be - included in protocol version 1.x. - - 7. Channel Message Payload needs slight redesining to include the IV - field to the MAC generation of the payload. It is authenticated - by the packet's MAC but not by the payload's MAC. Since the IV - belongs to the payload, its integrity should be protected by the - payload MAC and not alone by packet MAC. To be included in protocol - version 1.1. - - 16. Add STATS command after all to the protocol for providing practically - same information client gets when connects to a server. Normal - server would send this to router always when received from client. - 17. Cell wide channel founder support, and permanent channels when founder mode set. 18. Describe the SSH public key, X509, OpenPGP and SPKI certificates encoding format in SKE (from their respective definitions). + o Inviting and banning by public key should be made possible. To be + included in protocol version 1.2. + o UTF-8 support/requirement for nicknames & channel names. UTF-8 support in terminals and OS's are so hazy that this matter is left for consideration in next version of the protocol (1.2). For good UTF-8 diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 98f1a29c..d2622a08 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -56,6 +56,7 @@ SilcServerCommand silc_command_list[] = SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG), 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(stats, STATS, SILC_CF_LAG | SILC_CF_REG), 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_STRICT | SILC_CF_REG), @@ -2776,7 +2777,7 @@ SILC_SERVER_CMD_FUNC(kill) /* Update statistics */ if (remote_client->connection) server->stat.my_clients--; - if (server->server_type == SILC_ROUTER) + if (server->stat.cell_clients) server->stat.cell_clients--; SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR); SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR); @@ -2990,6 +2991,102 @@ SILC_SERVER_CMD_FUNC(ping) silc_server_command_free(cmd); } +/* Server side of command STATS. */ + +SILC_SERVER_CMD_FUNC(stats) +{ + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcServerID *server_id; + unsigned char *tmp; + SilcUInt32 tmp_len; + SilcBuffer packet, stats; + SilcUInt16 ident = silc_command_get_ident(cmd->payload); + SilcUInt32 uptime; + + SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1); + + /* Get Server ID */ + tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); + if (!tmp) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO, + SILC_STATUS_ERR_NO_SERVER_ID); + goto out; + } + server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); + if (!server_id) + goto out; + + /* The ID must be ours */ + if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO, + SILC_STATUS_ERR_NO_SUCH_SERVER); + silc_free(server_id); + goto out; + } + silc_free(server_id); + + /* If we are router then just send everything we got. If we are normal + server then we'll send this to our router to get all the latest + statistical information. */ + if (!cmd->pending && server->server_type != SILC_ROUTER && + !server->standalone) { + /* Send request to our router */ + SilcBuffer idp = silc_id_payload_encode(server->router->id, + SILC_ID_SERVER); + packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, + ++server->cmd_ident, 1, + 1, idp->data, idp->len); + silc_server_packet_send(server, server->router->connection, + SILC_PACKET_COMMAND, 0, packet->data, + packet->len, FALSE); + + /* Reprocess this packet after received reply from router */ + silc_server_command_pending(server, SILC_COMMAND_STATS, + server->cmd_ident, + silc_server_command_stats, + silc_server_command_dup(cmd)); + cmd->pending = TRUE; + silc_buffer_free(packet); + silc_buffer_free(idp); + goto out; + } + + /* Send our reply to sender */ + uptime = time(NULL) - server->starttime; + + stats = silc_buffer_alloc_size(60); + silc_buffer_format(stats, + SILC_STR_UI_INT(server->starttime), + SILC_STR_UI_INT(uptime), + SILC_STR_UI_INT(server->stat.my_clients), + SILC_STR_UI_INT(server->stat.my_channels), + SILC_STR_UI_INT(server->stat.my_server_ops), + SILC_STR_UI_INT(server->stat.my_router_ops), + SILC_STR_UI_INT(server->stat.cell_clients), + SILC_STR_UI_INT(server->stat.cell_channels), + SILC_STR_UI_INT(server->stat.cell_servers), + SILC_STR_UI_INT(server->stat.clients), + SILC_STR_UI_INT(server->stat.channels), + SILC_STR_UI_INT(server->stat.servers), + SILC_STR_UI_INT(server->stat.routers), + SILC_STR_UI_INT(server->stat.server_ops), + SILC_STR_UI_INT(server->stat.router_ops), + SILC_STR_END); + + packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, + SILC_STATUS_OK, ident, 2, + 2, tmp, tmp_len, + 3, stats->data, stats->len); + silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, + 0, packet->data, packet->len, FALSE); + silc_buffer_free(packet); + silc_buffer_free(stats); + + out: + silc_server_command_free(cmd); +} + /* 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. */ @@ -3470,8 +3567,7 @@ SILC_SERVER_CMD_FUNC(join) /* Check whether the channel was created by our router */ if (cmd->pending && context2) { - SilcServerCommandReplyContext reply = - (SilcServerCommandReplyContext)context2; + SilcServerCommandReplyContext reply = context2; if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) { tmp = silc_argument_get_arg_type(reply->args, 6, NULL); diff --git a/apps/silcd/command.h b/apps/silcd/command.h index 0b59e75f..b8441b7f 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -130,6 +130,7 @@ SILC_SERVER_CMD_FUNC(invite); SILC_SERVER_CMD_FUNC(quit); SILC_SERVER_CMD_FUNC(kill); SILC_SERVER_CMD_FUNC(info); +SILC_SERVER_CMD_FUNC(stats); SILC_SERVER_CMD_FUNC(ping); SILC_SERVER_CMD_FUNC(oper); SILC_SERVER_CMD_FUNC(join); diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 099d03d9..6300ebc1 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -55,6 +55,7 @@ SilcServerCommandReply silc_command_reply_list[] = SILC_SERVER_CMD_REPLY(info, INFO), SILC_SERVER_CMD_REPLY(motd, MOTD), SILC_SERVER_CMD_REPLY(join, JOIN), + SILC_SERVER_CMD_REPLY(stats, STATS), SILC_SERVER_CMD_REPLY(users, USERS), SILC_SERVER_CMD_REPLY(getkey, GETKEY), SILC_SERVER_CMD_REPLY(list, LIST), @@ -872,19 +873,14 @@ SILC_SERVER_CMD_REPLY_FUNC(join) /* If the channel is found from global list we must move it to the local list. */ - entry = silc_idlist_find_channel_by_name(server->global_list, + entry = silc_idlist_find_channel_by_name(server->global_list, channel_name, &cache); - if (entry) { - if (entry->rekey) { - silc_schedule_task_del_by_context(server->schedule, entry->rekey); - SILC_LOG_ERROR(("global_list->channels: entry->rekey != NULL, inform Pekka now!!!")); - } + if (entry) silc_idlist_del_channel(server->global_list, entry); - } /* Add the channel to our local list. */ - entry = silc_idlist_add_channel(server->local_list, strdup(channel_name), - SILC_CHANNEL_MODE_NONE, id, + entry = silc_idlist_add_channel(server->local_list, strdup(channel_name), + SILC_CHANNEL_MODE_NONE, id, server->router, NULL, hmac, 0); if (!entry) { silc_free(id); @@ -972,6 +968,46 @@ SILC_SERVER_CMD_REPLY_FUNC(join) silc_buffer_free(client_mode_list); } +/* Received reply to STATS command. */ + +SILC_SERVER_CMD_REPLY_FUNC(stats) +{ + SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context; + SilcServer server = cmd->server; + SilcCommandStatus status; + unsigned char *tmp; + SilcUInt32 tmp_len; + SilcBufferStruct buf; + + COMMAND_CHECK_STATUS; + + /* Get statistics structure */ + tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len); + if (server->server_type == SILC_SERVER && tmp) { + silc_buffer_set(&buf, tmp, tmp_len); + silc_buffer_unformat(&buf, + SILC_STR_UI_INT(NULL), + SILC_STR_UI_INT(NULL), + SILC_STR_UI_INT(NULL), + SILC_STR_UI_INT(NULL), + SILC_STR_UI_INT(NULL), + SILC_STR_UI_INT(NULL), + SILC_STR_UI_INT(&server->stat.cell_clients), + SILC_STR_UI_INT(&server->stat.cell_channels), + SILC_STR_UI_INT(&server->stat.cell_servers), + SILC_STR_UI_INT(&server->stat.clients), + SILC_STR_UI_INT(&server->stat.channels), + SILC_STR_UI_INT(&server->stat.servers), + SILC_STR_UI_INT(&server->stat.routers), + SILC_STR_UI_INT(&server->stat.server_ops), + SILC_STR_UI_INT(&server->stat.router_ops), + SILC_STR_END); + } + + out: + SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS); +} + SILC_SERVER_CMD_REPLY_FUNC(users) { SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context; diff --git a/apps/silcd/command_reply.h b/apps/silcd/command_reply.h index 17422bf4..9156e298 100644 --- a/apps/silcd/command_reply.h +++ b/apps/silcd/command_reply.h @@ -72,6 +72,7 @@ SILC_SERVER_CMD_REPLY_FUNC(identify); SILC_SERVER_CMD_REPLY_FUNC(info); SILC_SERVER_CMD_REPLY_FUNC(motd); SILC_SERVER_CMD_REPLY_FUNC(join); +SILC_SERVER_CMD_REPLY_FUNC(stats); SILC_SERVER_CMD_REPLY_FUNC(users); SILC_SERVER_CMD_REPLY_FUNC(getkey); SILC_SERVER_CMD_REPLY_FUNC(list); diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 56f01569..f58aadcb 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -331,7 +331,7 @@ void silc_server_notify(SilcServer server, /* Update statistics */ server->stat.clients--; - if (server->server_type == SILC_ROUTER) + if (server->stat.cell_clients) server->stat.cell_clients--; SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); @@ -1039,7 +1039,7 @@ void silc_server_notify(SilcServer server, /* Update statistics */ server->stat.clients--; - if (server->server_type == SILC_ROUTER) + if (server->stat.cell_clients) server->stat.cell_clients--; SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); @@ -1917,15 +1917,18 @@ SilcClientEntry silc_server_new_client(SilcServer server, SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("Your host is %s, running version %s", server->server_name, server_version)); - if (server->server_type == SILC_ROUTER) { + + if (server->stat.clients && server->stat.servers + 1) SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("There are %d clients on %d servers in SILC " "Network", server->stat.clients, server->stat.servers + 1)); + if (server->stat.cell_clients && server->stat.cell_servers + 1) SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("There are %d clients on %d server in our cell", server->stat.cell_clients, server->stat.cell_servers + 1)); + if (server->server_type == SILC_ROUTER) { SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("I have %d clients, %d channels, %d servers and " "%d routers", @@ -1933,24 +1936,25 @@ SilcClientEntry silc_server_new_client(SilcServer server, server->stat.my_channels, server->stat.my_servers, server->stat.my_routers)); + } else { + SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, + ("I have %d clients and %d channels formed", + server->stat.my_clients, + server->stat.my_channels)); + } + + if (server->stat.server_ops || server->stat.router_ops) SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("There are %d server operators and %d router " "operators online", server->stat.server_ops, server->stat.router_ops)); + if (server->stat.my_router_ops + server->stat.my_server_ops) SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("I have %d operators online", server->stat.my_router_ops + server->stat.my_server_ops)); - } else { - SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, - ("I have %d clients and %d channels formed", - server->stat.my_clients, - server->stat.my_channels)); - SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, - ("%d operators online", - server->stat.my_server_ops)); - } + SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE, ("Your connection is secured with %s cipher, " "key length %d bits", diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 6f22636a..306cb07f 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -44,6 +44,7 @@ SILC_TASK_CALLBACK(silc_server_timeout_remote); SILC_TASK_CALLBACK(silc_server_channel_key_rekey); SILC_TASK_CALLBACK(silc_server_failure_callback); SILC_TASK_CALLBACK(silc_server_rekey_callback); +SILC_TASK_CALLBACK(silc_server_get_stats); /* Allocates a new SILC server object. This has to be done before the server can be used. After allocation one must call silc_server_init to initialize @@ -148,6 +149,8 @@ bool silc_server_init(SilcServer server) SILC_LOG_DEBUG(("Initializing server")); + server->starttime = time(NULL); + /* Take config object for us */ silc_server_config_ref(&server->config_ref, server->config, server->config); @@ -338,6 +341,13 @@ bool silc_server_init(SilcServer server) (void *)purge, purge->timeout, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); + /* If we are normal server we'll retrieve network statisticial information + once in a while from the router. */ + if (server->server_type == SILC_SERVER) + silc_schedule_task_add(purge->schedule, 0, silc_server_get_stats, + server, 10, 0, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_LOW); + SILC_LOG_DEBUG(("Server initialized")); /* We are done here, return succesfully */ @@ -1425,8 +1435,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) /* Statistics */ server->stat.my_clients++; server->stat.clients++; - if (server->server_type == SILC_ROUTER) - server->stat.cell_clients++; + server->stat.cell_clients++; /* Get connection parameters */ if (conn->param) { @@ -2492,7 +2501,7 @@ void silc_server_free_client_data(SilcServer server, /* Update statistics */ server->stat.my_clients--; server->stat.clients--; - if (server->server_type == SILC_ROUTER) + if (server->stat.cell_clients) server->stat.cell_clients--; SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); @@ -4207,3 +4216,30 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final) silc_ske_free(ctx->ske); silc_free(ctx); } + +/* Task callback used to retrieve network statistical information from + router server once in a while. */ + +SILC_TASK_CALLBACK(silc_server_get_stats) +{ + SilcServer server = (SilcServer)context; + SilcBuffer idp, packet; + + SILC_LOG_DEBUG(("Retrieving stats from router")); + + if (!server->standalone) { + idp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER); + packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, + ++server->cmd_ident, 1, + 1, idp->data, idp->len); + silc_server_packet_send(server, server->router->connection, + SILC_PACKET_COMMAND, 0, packet->data, + packet->len, FALSE); + silc_buffer_free(packet); + silc_buffer_free(idp); + } + + silc_schedule_task_add(server->schedule, 0, silc_server_get_stats, + server, 120, 0, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_LOW); +} diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index f84566fc..7a6a9253 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -69,6 +69,7 @@ struct SilcServerStruct { SilcUInt32 id_string_len; SilcIdType id_type; + SilcUInt32 starttime; bool standalone; /* TRUE if server is standalone, and does not have connection to network. */ bool listenning; /* TRUE if server is listenning for diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 01870b95..5e9bdbd7 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -216,7 +216,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, /* Update statistics */ server->stat.clients--; - if (server->server_type == SILC_ROUTER) + if (server->stat.cell_clients) server->stat.cell_clients--; SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); @@ -280,7 +280,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, /* Update statistics */ server->stat.clients--; - if (server->server_type == SILC_ROUTER) + if (server->stat.cell_clients) server->stat.cell_clients--; SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); diff --git a/doc/draft-riikonen-silc-commands-03.nroff b/doc/draft-riikonen-silc-commands-03.nroff index b5d03877..6bf956d6 100644 --- a/doc/draft-riikonen-silc-commands-03.nroff +++ b/doc/draft-riikonen-silc-commands-03.nroff @@ -709,7 +709,59 @@ List of all defined commands in SILC follows. SILC_STATUS_ERR_NO_SERVER_ID - 11 + 11 SILC_COMMAND_STATS + + Max Arguments: 1 + Arguments: (1) + + This command is used to fetch various statistical information + from the server indicated by , which is the ID of + server where sender is connected to. Server receiving this + command MAY also send this further to its router for fetching + other cell and network wide statistics to accompany the reply. + + Reply messages to the command: + + Max Arguments: 3 + Arguments: (1) (2) + (3) [] + + This command replies with the Server ID of the server and + optional statistics structure which includes 32 bit MSB first + ordered integer values to represent various statistical + information. The structure is as follows: + + starttime - time when server was started + uptime - uptime of the server + my clients - number of locally connected clients + my channels - number of locally created channels + my server ops - number of local server operators + my router ops - number of local router operators + cell clients - number of clients in local cell + cell channels - number of channels in local cell + cell servers - number of servers in local cell + clients - number of client in SILC network + channels - number of channels in SILC network + servers - number of servers in SILC network + routers - number of routers in SILC network + server ops - number of server operators in SILC network + router ops - number of router operators in SILC network + + If some value is unknown it is set to zero (0) value. The + "starttime" is the start time of the server, and is seconds + since Epoch (POSIX.1). The "uptime" is time difference of + current time and "starttime" in the server, and is seconds + in value. + + Status messages: + + SILC_STATUS_OK + SILC_STATUS_ERR_NOT_REGISTERED + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS + SILC_STATUS_ERR_TOO_MANY_PARAMS + SILC_STATUS_ERR_NO_SUCH_SERVER_ID + SILC_STATUS_ERR_NO_SUCH_SERVER + SILC_STATUS_ERR_NO_SERVER_ID 12 SILC_COMMAND_PING diff --git a/doc/draft-riikonen-silc-pp-05.nroff b/doc/draft-riikonen-silc-pp-05.nroff index 9c8a5cc6..91bdc933 100644 --- a/doc/draft-riikonen-silc-pp-05.nroff +++ b/doc/draft-riikonen-silc-pp-05.nroff @@ -1647,12 +1647,12 @@ o Padding (variable length) - The padding that MUST be other parts of the packet. o MAC (variable length) - The MAC computed from the - Message Length, Message Data, Padding Length and Padding - fields. This protects the integrity of the plaintext - channel message. The receiver can verify from the MAC - whether the message decrypted correctly. Also, if more than - one private key has been set for the channel, the receiver - can verify which of the keys decrypted the message + Message Length, Message Data, Padding Length, Padding and + Initial Vector fields. This protects the integrity of the + plaintext channel message. The receiver can verify from + the MAC whether the message decrypted correctly. Also, if + more than one private key has been set for the channel, the + receiver can verify which of the keys decrypted the message correctly. Note that, this field is encrypted and MUST be added to the padding calculation. diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 797b464e..80182f5a 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -306,7 +306,7 @@ void silc_client_notify_by_server(SilcClient client, /* Some client implementations actually quit network by first doing LEAVE and then immediately SIGNOFF. We'll check for this by doing - check for the client after 5 - 14 seconds. If it is not valid after + check for the client after 5 - 34 seconds. If it is not valid after that we'll remove the client from cache. */ if (!silc_hash_table_count(client_entry->channels)) { SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res)); @@ -314,7 +314,7 @@ void silc_client_notify_by_server(SilcClient client, res->packet = silc_id_dup(client_id, SILC_ID_CLIENT); silc_schedule_task_add(client->schedule, 0, silc_client_notify_check_client, conn, - (5 + (silc_rng_get_rn16(client->rng) % 9)), + (5 + (silc_rng_get_rn16(client->rng) % 29)), 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); } diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 289b1917..616b2d86 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -615,19 +615,53 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) SILC_CLIENT_CMD_REPLY_FUNC(list) { SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; unsigned char *tmp, *name, *topic; - SilcUInt32 usercount = 0; + SilcUInt32 usercount = 0, len; + SilcChannelID *channel_id = NULL; + SilcChannelEntry channel_entry; COMMAND_CHECK_STATUS_LIST; + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (!tmp) { + COMMAND_REPLY_ERROR; + goto out; + } + + channel_id = silc_id_payload_parse_id(tmp, len, NULL); + if (!channel_id) { + COMMAND_REPLY_ERROR; + goto out; + } + name = silc_argument_get_arg_type(cmd->args, 3, NULL); + if (!name) { + COMMAND_REPLY_ERROR; + goto out; + } + topic = silc_argument_get_arg_type(cmd->args, 4, NULL); tmp = silc_argument_get_arg_type(cmd->args, 5, NULL); if (tmp) SILC_GET32_MSB(usercount, tmp); + /* Check whether the channel exists, and add it to cache if it doesn't. */ + channel_entry = silc_client_get_channel_by_id(cmd->client, conn, + channel_id); + if (!channel_entry) { + /* Add new channel entry */ + channel_entry = silc_client_add_channel(cmd->client, conn, name, 0, + channel_id); + if (!channel_entry) { + COMMAND_REPLY_ERROR; + goto out; + } + channel_id = NULL; + } + /* Notify application */ - COMMAND_REPLY((ARGS, NULL, name, topic, usercount)); + COMMAND_REPLY((ARGS, channel_entry, name, topic, usercount)); /* Pending callbacks are not executed if this was an list entry */ if (cmd->status != SILC_STATUS_OK && @@ -637,6 +671,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(list) } out: + silc_free(channel_id); SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LIST); silc_client_command_reply_free(cmd); } diff --git a/lib/silccore/silcchannel.c b/lib/silccore/silcchannel.c index 2a853548..2bd7eb6f 100644 --- a/lib/silccore/silcchannel.c +++ b/lib/silccore/silcchannel.c @@ -299,7 +299,10 @@ bool silc_channel_message_payload_decrypt(unsigned char *data, /* Check the MAC of the message */ SILC_LOG_DEBUG(("Checking channel message MACs")); - silc_hmac_make(hmac, dst, (data_len - iv_len - mac_len), mac2, &mac_len); + silc_hmac_init(hmac); + silc_hmac_update(hmac, dst, (data_len - iv_len - mac_len)); + silc_hmac_update(hmac, data + (data_len - iv_len), iv_len); + silc_hmac_final(hmac, mac2, &mac_len); if (memcmp(mac, mac2, mac_len)) { SILC_LOG_DEBUG(("Channel message MACs does not match")); silc_free(dst); @@ -395,7 +398,10 @@ bool silc_channel_message_payload_encrypt(unsigned char *data, SilcBufferStruct buf; /* Compute the MAC of the channel message data */ - silc_hmac_make(hmac, data, data_len, mac, &mac_len); + silc_hmac_init(hmac); + silc_hmac_update(hmac, data, data_len); + silc_hmac_update(hmac, iv, iv_len); + silc_hmac_final(hmac, mac, &mac_len); /* Put rest of the data to the payload */ silc_buffer_set(&buf, data, true_len); diff --git a/lib/silccore/silccommand.h b/lib/silccore/silccommand.h index 4e84bd5b..d1888553 100644 --- a/lib/silccore/silccommand.h +++ b/lib/silccore/silccommand.h @@ -134,6 +134,7 @@ typedef unsigned char SilcCommand; #define SILC_COMMAND_QUIT 8 #define SILC_COMMAND_KILL 9 #define SILC_COMMAND_INFO 10 +#define SILC_COMMAND_STATS 11 #define SILC_COMMAND_PING 12 #define SILC_COMMAND_OPER 13 #define SILC_COMMAND_JOIN 14 diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 46941045..756d505d 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -81,6 +81,7 @@ void silc_ske_free(SilcSKE ske) silc_ske_payload_ke_free(ske->ke1_payload); if (ske->ke2_payload) silc_ske_payload_ke_free(ske->ke2_payload); + silc_free(ske->remote_version); /* Free rest */ if (ske->prop) { @@ -1216,6 +1217,8 @@ silc_ske_select_security_properties(SilcSKE ske, } } + ske->remote_version = silc_memdup(rp->version, rp->version_len); + /* Flags are returned unchanged. */ payload->flags = rp->flags; @@ -2006,7 +2009,7 @@ bool silc_ske_parse_version(SilcSKE ske, char **software_version_string, char **vendor_version) { - return silc_parse_version_string(ske->start_payload->version, + return silc_parse_version_string(ske->remote_version, protocol_version, protocol_version_string, software_version, diff --git a/lib/silcske/silcske.h b/lib/silcske/silcske.h index 7d0aab9e..4db724bf 100644 --- a/lib/silcske/silcske.h +++ b/lib/silcske/silcske.h @@ -335,6 +335,7 @@ struct SilcSKEStruct { SilcSKEStartPayload *start_payload; SilcSKEKEPayload *ke1_payload; SilcSKEKEPayload *ke2_payload; + unsigned char *remote_version; /* Temporary copy of the KE Start Payload used in the HASH computation. */