From 528c3c9e24c813f5eb404b34f3090c2f16e78ce1 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 18 Mar 2001 21:38:10 +0000 Subject: [PATCH] updates. --- CHANGES | 39 ++++++++ README | 5 + TODO | 17 +++- apps/silcd/command.c | 98 ++++++++++++++++++- apps/silcd/packet_receive.c | 129 +++++++++++++++++++++++++- apps/silcd/packet_send.c | 50 ++++++++++ apps/silcd/packet_send.h | 12 +++ apps/silcd/server.c | 42 ++++++--- apps/silcd/server.h | 4 +- apps/silcd/testi2.conf | 12 +-- doc/draft-riikonen-silc-pp-01.nroff | 97 ++++++++++++++++++- doc/draft-riikonen-silc-spec-01.nroff | 71 ++++++++++++++ lib/silccore/silcnotify.h | 1 + lib/silccore/silcpacket.h | 1 + 14 files changed, 544 insertions(+), 34 deletions(-) diff --git a/CHANGES b/CHANGES index 84f84aba..65971497 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,42 @@ +Sun Mar 18 21:02:47 EET 2001 Pekka Riikonen + + * Added SILC_NOTIFY_TYPE_KILLED notify type. It is sent when + an client is killed from the SILC Network. Updated the protocol + specs accordingly. + + Added new function silc_server_send_notify_killed to the + silcd/packet_send.[ch]. + + * Added function silc_server_packet_relay_notify to relay notify + packets that are destined directly to a client. In this case + the server does not process the notify packets but merely relays + it to the client. Affected file silcd/packet_send.[ch]. + + Added also silc_server_packet_process_relay_notify to check + whereto relay the notify. Affected file is + silcd/packet_receive.[ch]. + + * Implemented KILL command to the server. + + * Updated TODO. + + * Added the backup schema desgined last fall to the protocol + specs for everyone to see. The specification is in the + *-spec-xx.txt draft and the packet type definitions for the + backup routers is in *-pp-xx.txt draft. Thusly, added also + new packet type SILC_PACKET_CELL_ROUTERS. + + * A big security problem in the implementation discovered. The + signoff of an client did not cause new channel key generation + which it of course should've done. The channel keys must be + always re-generated when client leaves (or signoffs) the channel. + The silc_server_remove_from_channels funtion now handles + the channel key re-generation. + + * Added `sender' argument to the silc_server_send_notify_on_channels + to not to send the client provided as argument. Affected file + silcd/packet_send.[ch]. + Fri Mar 16 15:52:49 EET 2001 Pekka Riikonen * Implemented OPER and SILCOPER commands into the server and diff --git a/README b/README index 191ebd1e..559ae953 100644 --- a/README +++ b/README @@ -178,6 +178,11 @@ Following commands has been, at least partly, implemented: Obtains router operator privileges. + /KILL [] + + Router operator can use this command to remove an client + from the SILC Network temporarily. + /CONNECT [] Connects to server the remote . You must be diff --git a/TODO b/TODO index e524e5bb..133d751a 100644 --- a/TODO +++ b/TODO @@ -100,15 +100,22 @@ TODO In SILC Client Library TODO In SILC Server =================== - o Packet processing can be made faster. All packet function in the - packet_receive.c has same prototypes. Instead of calling those from - huge switch() make a table of callback functions that can be called - directly by the packet type. + o Functions such as silc_server_private_message, + silc_server_private_message_key and + silc_server_packet_process_relay_notify can be optimized. I don't think + we need such a big lookups to lookup the router to the destination, + it is already provided in the client entry. o silc_server_send_key_agreement and silc_server_send_private_message_key are one and same function (also silc_server_send_private_message is almost same function). These should be unified to one generic named - function and use that. + function and use that (silc_server_packet_relay_notify is also + same function). + + o Packet processing can be made faster. All packet function in the + packet_receive.c has same prototypes. Instead of calling those from + huge switch() make a table of callback functions that can be called + directly by the packet type. o DNS/IP lookup blocks the server. This must be fixed. Check the resolver stuff (resolver(3), resolver(5)). Either we have to do the diff --git a/apps/silcd/command.c b/apps/silcd/command.c index ef844c0a..4133e7ce 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -59,7 +59,7 @@ SilcServerCommand silc_command_list[] = 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(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(restart, RESTART, @@ -1686,7 +1686,7 @@ SILC_SERVER_CMD_FUNC(nick) nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); /* Send NICK_CHANGE notify to the client's channels */ - silc_server_send_notify_on_channels(server, client, + silc_server_send_notify_on_channels(server, NULL, client, SILC_NOTIFY_TYPE_NICK_CHANGE, 2, oidp->data, oidp->len, nidp->data, nidp->len); @@ -2010,8 +2010,102 @@ SILC_SERVER_CMD_FUNC(quit) silc_server_command_free(cmd); } +/* Server side of command KILL. This command is used by router operator + to remove an client from the SILC Network temporarily. */ + SILC_SERVER_CMD_FUNC(kill) { + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; + SilcClientEntry remote_client; + SilcClientID *client_id; + unsigned char *tmp, *comment; + unsigned int tmp_len; + SilcBuffer idp; + + SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2); + + if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) + goto out; + + if (server->server_type != SILC_ROUTER) + goto out; + + /* Check whether client has the permissions. */ + if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_ERR_NO_ROUTER_PRIV); + goto out; + } + + /* Get the client ID */ + tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); + if (!tmp) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + client_id = silc_id_payload_parse_id(tmp, tmp_len); + if (!client_id) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_ERR_NO_SUCH_CLIENT_ID); + goto out; + } + + /* Get the client entry */ + remote_client = silc_idlist_find_client_by_id(server->local_list, + client_id, NULL); + if (!remote_client) { + remote_client = silc_idlist_find_client_by_id(server->global_list, + client_id, NULL); + if (!remote_client) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_ERR_NO_SUCH_CLIENT_ID); + goto out; + } + } + + /* Get comment */ + comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); + + /* Send reply to the sender */ + silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL, + SILC_STATUS_OK); + + /* Send KILLED notify to the channels. It is not sent to the client + as it will be sent differently destined directly to the client and not + to the channel. */ + idp = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT); + silc_server_send_notify_on_channels(server, remote_client->connection, + remote_client, SILC_NOTIFY_TYPE_KILLED, + comment ? 2 : 1, + idp->data, idp->len, + comment, comment ? strlen(comment) : 0); + silc_buffer_free(idp); + + /* Remove the client from all channels. This generates new keys to the + channels as well. */ + silc_server_remove_from_channels(server, NULL, remote_client, FALSE, + NULL, TRUE); + + /* Send KILLED notify to the client directly */ + silc_server_send_notify_killed(server, remote_client->connection ? + remote_client->connection : + remote_client->router->connection, FALSE, + remote_client->id, SILC_ID_CLIENT_LEN, + comment); + + /* Send KILLED notify to primary route */ + if (!server->standalone) + silc_server_send_notify_killed(server, server->router->connection, + server->server_type == SILC_ROUTER ? + TRUE : FALSE, + remote_client->id, SILC_ID_CLIENT_LEN, + comment); + + out: + silc_server_command_free(cmd); } /* Server side of command INFO. This sends information about us to diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 55ed8819..83e19b8e 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -27,6 +27,99 @@ extern char *server_version; +/* Check whereto relay the received notify packet that was destined + to a client. */ + +static void +silc_server_packet_process_relay_notify(SilcServer server, + SilcSocketConnection sock, + SilcPacketContext *packet) +{ + SilcClientID *id; + SilcServerEntry router; + SilcSocketConnection dst_sock; + SilcClientEntry client; + SilcIDListData idata; + + SILC_LOG_DEBUG(("Start")); + + /* Decode destination Client ID */ + id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT); + if (!id) { + SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); + return; + } + + /* If the destination belongs to our server we don't have to route + the packet anywhere but to send it to the local destination. */ + client = silc_idlist_find_client_by_id(server->local_list, id, NULL); + if (client) { + /* It exists, now deliver the packet to the destination */ + dst_sock = (SilcSocketConnection)client->connection; + + /* If we are router and the client has router then the client is in + our cell but not directly connected to us. */ + if (server->server_type == SILC_ROUTER && client->router) { + /* We are of course in this case the client's router thus the real + "router" of the client is the server who owns the client. Thus + we will send the packet to that server. */ + router = (SilcServerEntry)client->router; + idata = (SilcIDListData)router; + silc_server_packet_relay_notify(server, router->connection, + idata->send_key, + idata->hmac, + packet); + silc_free(id); + return; + } + + /* Seems that client really is directly connected to us */ + idata = (SilcIDListData)client; + silc_server_packet_relay_notify(server, dst_sock, + idata->send_key, + idata->hmac, packet); + silc_free(id); + return; + } + + /* Destination belongs to someone not in this server. If we are normal + server our action is to send the packet to our router. */ + if (server->server_type == SILC_SERVER && !server->standalone) { + router = server->router; + + /* Send to primary route */ + if (router) { + dst_sock = (SilcSocketConnection)router->connection; + idata = (SilcIDListData)router; + silc_server_packet_relay_notify(server, dst_sock, + idata->send_key, + idata->hmac, packet); + } + silc_free(id); + return; + } + + /* We are router and we will perform route lookup for the destination + and send the packet to fastest route. */ + if (server->server_type == SILC_ROUTER && !server->standalone) { + /* Check first that the ID is valid */ + client = silc_idlist_find_client_by_id(server->global_list, id, NULL); + if (client) { + dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT); + router = (SilcServerEntry)dst_sock->user_data; + idata = (SilcIDListData)router; + + /* Get fastest route and send packet. */ + if (router) + silc_server_packet_relay_notify(server, dst_sock, + idata->send_key, + idata->hmac, packet); + silc_free(id); + return; + } + } +} + /* Received notify packet. Server can receive notify packets from router. Server then relays the notify messages to clients if needed. */ @@ -52,6 +145,13 @@ void silc_server_notify(SilcServer server, packet->src_id_type != SILC_ID_SERVER) return; + /* If the packet is destined directly to a client, then we don't + process the packet at all but just relay it to the client. */ + if (packet->dst_id_type == SILC_ID_CLIENT) { + silc_server_packet_process_relay_notify(server, sock, packet); + return; + } + /* If we are router and this packet is not already broadcast packet we will broadcast it. The sending socket really cannot be router or the router is buggy. If this packet is coming from router then it must @@ -250,7 +350,7 @@ void silc_server_notify(SilcServer server, tmp = NULL; /* Remove the client from all channels */ - silc_server_remove_from_channels(server, NULL, client, tmp); + silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, TRUE); /* Remove the client entry */ if (!silc_idlist_del_client(server->global_list, client)) @@ -346,7 +446,7 @@ void silc_server_notify(SilcServer server, /* Send the NICK_CHANGE notify type to local clients on the channels this client is joined to. */ - silc_server_send_notify_on_channels(server, client, + silc_server_send_notify_on_channels(server, NULL, client, SILC_NOTIFY_TYPE_NICK_CHANGE, 2, id, tmp_len, id2, tmp_len); @@ -538,6 +638,15 @@ void silc_server_notify(SilcServer server, break; + case SILC_NOTIFY_TYPE_KILLED: + /* + * Distribute the notify to local clients on channels + */ + + SILC_LOG_DEBUG(("KILLED notify")); + + break; + /* Ignore rest of the notify types for now */ case SILC_NOTIFY_TYPE_NONE: case SILC_NOTIFY_TYPE_MOTD: @@ -655,6 +764,7 @@ void silc_server_private_message(SilcServer server, idata->send_key, idata->hmac, packet); + silc_free(id); return; } @@ -663,6 +773,7 @@ void silc_server_private_message(SilcServer server, silc_server_send_private_message(server, dst_sock, idata->send_key, idata->hmac, packet); + silc_free(id); return; } @@ -679,6 +790,7 @@ void silc_server_private_message(SilcServer server, idata->send_key, idata->hmac, packet); } + silc_free(id); return; } @@ -697,6 +809,7 @@ void silc_server_private_message(SilcServer server, silc_server_send_private_message(server, dst_sock, idata->send_key, idata->hmac, packet); + silc_free(id); return; } } @@ -752,6 +865,7 @@ void silc_server_private_message_key(SilcServer server, idata->send_key, idata->hmac, packet); + silc_free(id); return; } @@ -760,6 +874,7 @@ void silc_server_private_message_key(SilcServer server, silc_server_send_private_message_key(server, dst_sock, idata->send_key, idata->hmac, packet); + silc_free(id); return; } @@ -776,6 +891,7 @@ void silc_server_private_message_key(SilcServer server, idata->send_key, idata->hmac, packet); } + silc_free(id); return; } @@ -794,6 +910,7 @@ void silc_server_private_message_key(SilcServer server, silc_server_send_private_message_key(server, dst_sock, idata->send_key, idata->hmac, packet); + silc_free(id); return; } } @@ -1677,10 +1794,10 @@ void silc_server_key_agreement(SilcServer server, } /* If the destination belongs to our server we don't have to route - the message anywhere but to send it to the local destination. */ + the packet anywhere but to send it to the local destination. */ client = silc_idlist_find_client_by_id(server->local_list, id, NULL); if (client) { - /* It exists, now deliver the message to the destination */ + /* It exists, now deliver the packet to the destination */ dst_sock = (SilcSocketConnection)client->connection; /* If we are router and the client has router then the client is in @@ -1695,6 +1812,7 @@ void silc_server_key_agreement(SilcServer server, idata->send_key, idata->hmac, packet); + silc_free(id); return; } @@ -1703,6 +1821,7 @@ void silc_server_key_agreement(SilcServer server, silc_server_send_key_agreement(server, dst_sock, idata->send_key, idata->hmac, packet); + silc_free(id); return; } @@ -1719,6 +1838,7 @@ void silc_server_key_agreement(SilcServer server, idata->send_key, idata->hmac, packet); } + silc_free(id); return; } @@ -1737,6 +1857,7 @@ void silc_server_key_agreement(SilcServer server, silc_server_send_key_agreement(server, dst_sock, idata->send_key, idata->hmac, packet); + silc_free(id); return; } } diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 69bd04cd..1fbb0e59 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -1080,6 +1080,27 @@ void silc_server_send_notify_kicked(SilcServer server, silc_buffer_free(idp); } +/* Send KILLED notify type. This tells that the `client_id' client was + killed from the network. The `comment' may indicate the reason + for the killing. */ + +void silc_server_send_notify_killed(SilcServer server, + SilcSocketConnection sock, + int broadcast, + SilcClientID *client_id, + unsigned int client_id_len, + char *comment) +{ + SilcBuffer idp; + + idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT); + silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id, + SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED, + comment ? 2 : 1, idp->data, idp->len, + comment, comment ? strlen(comment) : 0); + silc_buffer_free(idp); +} + /* Sends notify message destined to specific entity. */ void silc_server_send_notify_dest(SilcServer server, @@ -1135,6 +1156,7 @@ void silc_server_send_notify_to_channel(SilcServer server, local servers if we are router). */ void silc_server_send_notify_on_channels(SilcServer server, + SilcSocketConnection sender, SilcClientEntry client, SilcNotifyType type, unsigned int argc, ...) @@ -1204,6 +1226,9 @@ void silc_server_send_notify_on_channels(SilcServer server, sock = (SilcSocketConnection)c->router->connection; idata = (SilcIDListData)c->router; + if (sender && sock == sender) + continue; + packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER); packetdata.dst_id_len = SILC_ID_SERVER_LEN; packetdata.dst_id_type = SILC_ID_SERVER; @@ -1239,6 +1264,9 @@ void silc_server_send_notify_on_channels(SilcServer server, sock = (SilcSocketConnection)c->connection; idata = (SilcIDListData)c; + if (sender && sock == sender) + continue; + packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT); packetdata.dst_id_len = SILC_ID_CLIENT_LEN; packetdata.dst_id_type = SILC_ID_CLIENT; @@ -1439,3 +1467,25 @@ void silc_server_send_private_message_key(SilcServer server, /* Send the packet */ silc_server_packet_send_real(server, dst_sock, FALSE); } + +/* Routine used to relay notify packets to a client. The notify packets + may be destined directly to a client and this routine is used to do + that. */ + +void silc_server_packet_relay_notify(SilcServer server, + SilcSocketConnection dst_sock, + SilcCipher cipher, + SilcHmac hmac, + SilcPacketContext *packet) +{ + silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len + + packet->dst_id_len + packet->padlen); + silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len); + silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len); + + /* Re-encrypt packet */ + silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len); + + /* Send the packet */ + silc_server_packet_send_real(server, dst_sock, FALSE); +} diff --git a/apps/silcd/packet_send.h b/apps/silcd/packet_send.h index b402c6aa..08bb1e62 100644 --- a/apps/silcd/packet_send.h +++ b/apps/silcd/packet_send.h @@ -162,6 +162,12 @@ void silc_server_send_notify_kicked(SilcServer server, SilcClientID *client_id, unsigned int client_id_len, char *comment); +void silc_server_send_notify_killed(SilcServer server, + SilcSocketConnection sock, + int broadcast, + SilcClientID *client_id, + unsigned int client_id_len, + char *comment); void silc_server_send_notify_dest(SilcServer server, SilcSocketConnection sock, int broadcast, @@ -176,6 +182,7 @@ void silc_server_send_notify_to_channel(SilcServer server, SilcNotifyType type, unsigned int argc, ...); void silc_server_send_notify_on_channels(SilcServer server, + SilcSocketConnection sender, SilcClientEntry client, SilcNotifyType type, unsigned int argc, ...); @@ -210,5 +217,10 @@ void silc_server_send_private_message_key(SilcServer server, SilcCipher cipher, SilcHmac hmac, SilcPacketContext *packet); +void silc_server_packet_relay_notify(SilcServer server, + SilcSocketConnection dst_sock, + SilcCipher cipher, + SilcHmac hmac, + SilcPacketContext *packet); #endif diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 47a62ddb..1487ee0f 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -1977,7 +1977,7 @@ void silc_server_free_client_data(SilcServer server, { FreeClientInternal i = silc_calloc(1, sizeof(*i)); - /* Send REMOVE_ID packet to routers. */ + /* Send SIGNOFF notify to routers. */ if (!server->standalone && server->router) silc_server_send_notify_signoff(server, server->router->connection, server->server_type == SILC_SERVER ? @@ -1985,7 +1985,7 @@ void silc_server_free_client_data(SilcServer server, SILC_ID_CLIENT_LEN, signoff); /* Remove client from all channels */ - silc_server_remove_from_channels(server, sock, client, signoff); + silc_server_remove_from_channels(server, sock, client, TRUE, signoff, TRUE); /* We will not delete the client entry right away. We will take it into history (for WHOWAS command) for 5 minutes */ @@ -2096,7 +2096,8 @@ int silc_server_remove_clients_by_server(SilcServer server, } /* Remove the client entry */ - silc_server_remove_from_channels(server, NULL, client, NULL); + silc_server_remove_from_channels(server, NULL, client, TRUE, + NULL, TRUE); silc_idlist_del_client(server->local_list, client); if (!silc_idcache_list_next(list, &id_cache)) @@ -2121,7 +2122,8 @@ int silc_server_remove_clients_by_server(SilcServer server, } /* Remove the client entry */ - silc_server_remove_from_channels(server, NULL, client, NULL); + silc_server_remove_from_channels(server, NULL, client, TRUE, + NULL, TRUE); silc_idlist_del_client(server->global_list, client); if (!silc_idcache_list_next(list, &id_cache)) @@ -2173,7 +2175,9 @@ int silc_server_channel_has_local(SilcChannelEntry channel) void silc_server_remove_from_channels(SilcServer server, SilcSocketConnection sock, SilcClientEntry client, - char *signoff_message) + int notify, + char *signoff_message, + int keygen) { SilcChannelEntry channel; SilcChannelClientEntry chl; @@ -2220,7 +2224,7 @@ void silc_server_remove_from_channels(SilcServer server, if (server->server_type == SILC_SERVER && !silc_server_channel_has_local(channel)) { /* Notify about leaving client if this channel has global users. */ - if (channel->global_users) + if (notify && channel->global_users) silc_server_send_notify_to_channel(server, NULL, channel, FALSE, SILC_NOTIFY_TYPE_SIGNOFF, signoff_message ? 2 : 1, @@ -2236,12 +2240,24 @@ void silc_server_remove_from_channels(SilcServer server, /* Send notify to channel about client leaving SILC and thus the entire channel. */ - silc_server_send_notify_to_channel(server, NULL, channel, FALSE, - SILC_NOTIFY_TYPE_SIGNOFF, - signoff_message ? 2 : 1, - clidp->data, clidp->len, - signoff_message, signoff_message ? - strlen(signoff_message) : 0); + if (notify) + silc_server_send_notify_to_channel(server, NULL, channel, FALSE, + SILC_NOTIFY_TYPE_SIGNOFF, + signoff_message ? 2 : 1, + clidp->data, clidp->len, + signoff_message, signoff_message ? + strlen(signoff_message) : 0); + + if (keygen) { + /* Re-generate channel key */ + silc_server_create_channel_key(server, channel, 0); + + /* Send the channel key to the channel. The key of course is not sent + to the client who was removed f rom the channel. */ + silc_server_send_channel_key(server, client->connection, channel, + server->server_type == SILC_ROUTER ? + FALSE : !server->standalone); + } } silc_buffer_free(clidp); @@ -2502,6 +2518,8 @@ void silc_server_create_channel_key(SilcServer server, unsigned char channel_key[32], hash[32]; unsigned int len; + SILC_LOG_DEBUG(("Generating channel key")); + if (!channel->channel_key) if (!silc_cipher_alloc("aes-256-cbc", &channel->channel_key)) return; diff --git a/apps/silcd/server.h b/apps/silcd/server.h index 296c35cc..e25f6f11 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -106,7 +106,9 @@ int silc_server_remove_clients_by_server(SilcServer server, void silc_server_remove_from_channels(SilcServer server, SilcSocketConnection sock, SilcClientEntry client, - char *signoff_message); + int notify, + char *signoff_message, + int keygen); int silc_server_remove_from_one_channel(SilcServer server, SilcSocketConnection sock, SilcChannelEntry channel, diff --git a/apps/silcd/testi2.conf b/apps/silcd/testi2.conf index 214b7f72..964d073e 100644 --- a/apps/silcd/testi2.conf +++ b/apps/silcd/testi2.conf @@ -3,7 +3,7 @@ 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-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 @@ -17,7 +17,7 @@ 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] @@ -31,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 @@ -55,10 +55,10 @@ errorlogfile:silcd2.log:10000 [AdminConnection] [ServerConnection] -10.2.1.7:passwd:priikone:1333:1:1 +212.146.42.253:passwd:priikone:1336: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] diff --git a/doc/draft-riikonen-silc-pp-01.nroff b/doc/draft-riikonen-silc-pp-01.nroff index 0b1dcf77..2a1dd374 100644 --- a/doc/draft-riikonen-silc-pp-01.nroff +++ b/doc/draft-riikonen-silc-pp-01.nroff @@ -726,7 +726,20 @@ List of SILC Packet types are defined as follows. Payload of the packet: See section 2.3.20 Key Agreement Payload - 26 - 199 + 26 SILC_PACKET_CELL_ROUTERS + + This packet is used by primary router in the cell to notify its + primary router what other routers (backup routers) exist in the + cell. In case of failure of the primary router in the cell the + first router in the list will act as primary router of the cell. + This packet may be sent at anytime after connection has been + registered to the primary router. The client must not send this + packet. + + Payload of the packet: See section 2.3.21 Cell Routers Payload + + + 27 - 199 Currently undefined commands. @@ -1214,6 +1227,24 @@ ID's sent in arguments are sent inside ID Payload. The kicker may have set the to indicate the reason for the kicking. + +13 SILC_NOTIFY_TYPE_KILLED + + Sent when a client has been killed from the network. This is sent + also to the client who was killed from the network. The client + who was killed from the network must be removed from the network. + This notify type is destined directly to the client who was killed + and to channel if the client is on any channel. The router or + server receiving the packet distributes this type to the local + clients on the channel and broadcast it to the network. + + Max Arguments: 2 + Arguments: (1) (2) [] + + The is the client who was killed from the network. + The killer may have set the to indicate the reason for + the killing. + .in 3 Notify types starting from 16384 are reserved for private notify @@ -1786,8 +1817,8 @@ set the real nickname of the user which is then used to create new client ID. The payload may only be sent with SILC_PACKET_NEW_CLIENT packet. It -must not be sent in any other packet type. The following diagram represents -the New Client Payload. +must not be sent in any other packet type. The following diagram +represents the New Client Payload. @@ -1979,7 +2010,6 @@ represents the Key Agreement Payload. Figure 20: Key Agreement Payload - .in 6 o Hostname Length (2 bytes) - Indicates the length of the Hostname field. @@ -2005,6 +2035,65 @@ it is intended to be used as private message keys. Any other use for the key material is undefined. +.ti 0 +2.3.21 Cell Routers Payload + +Cell Routers payload is used by router to notify its primary router what +other routers exist in the cell. The other routers are considered to be +backup routers and one of them will come active only in the case of +failure of the primary router. Normal server can send this packet if it +is acting as backup router. Client must not send this packet. To send +more than one backup router set the List flag and assemble the payloads +as list. + +The payload may only be sent with SILC_PACKET_CELL_ROUTERS packet. It +must not be sent in any other packet type. The Following diagram +represents the Cell Routers Payload. + + +.in 5 +.nf + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Hostname Length | | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +| | +~ Hostname ~ +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Port | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Server ID Length | | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +| | +~ Server ID ~ +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +.in 3 + +.ce +Figure 21: Cell Routers Payload + + +.in 6 +o Hostname Length (2 bytes) - Indicates the length of the Hostname + field. + +o Hostname (variable length) - The hostname or IP address of + the backup router. + +o Port (4 bytes) - The port of the backup router it currently uses. + This is a 32 bit MSB first order value. + +o Server ID Length (2 bytes) - Indicates the length of the Server + ID field. + +o Server ID (variable length) - Consists of the Server ID of the + backup router. +.in 3 + + .ti 0 2.4 SILC ID Types diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index 79e6fafd..ec7ba80c 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -79,6 +79,7 @@ Table of Contents 2.3 Communication in the Network .............................. 6 2.4 Channel Communication ..................................... 7 2.5 Router Connections ........................................ 7 + 2.6 Backup Routers ............................................ XX 3 SILC Specification ............................................ 8 3.1 Client .................................................... 8 3.1.1 Client ID ........................................... 9 @@ -417,6 +418,76 @@ broadcast packets. Usually all router wide information in the network is distributed by SILC broadcast packets. +.ti 0 +2.6 Backup Routers + +Backup routers may exist in the cell in addition of the primary router. +However, they must not be active routers and act as routers in the cell. +Only one router may be acting as primary router in the cell. In the case +of failure of the primary router may one of the backup routers become +active. The purpose of backup routers are in case of failure of the +primary router to maintain working connections inside the cell and outside +the cell and to avoid netsplits. + +Backup routers are normal servers in the cell that are prepared to take +over the tasks of primary router if needed. They need to have at least +one direct and active connection to the primary router of the cell. +This communication channel is used to send the router information to +the backup router. Backup router must know everything that the primary +router knows to be able to take over the tasks of the primary router. +It is the primary router's responsibility to feed the data to the backup +router. If the backup router does not know all the data in the case of +failure some connections may be lost. The primary router of the cell +must consider the backup router being normal router server and feed the +data accordingly. + +In addition of having direct connection to the primary router of the +cell the backup router must also have connection to the same router +the primary router of the cell has connected. However, it must not be +active router connection meaning that the backup router must not use +that channel as its primary route and it must not notify the router +about having connected servers, channels and clients behind it. It +merely connects to the router. This sort of connection is later +referred as being passive connection. Some keepalive actions may be +needed by the router to keep the connection alive. + +The primary router notifies its primary router about having backup +routers in the cell by sending SILC_PACKET_CELL_ROUTERS packet. If +and when the primary router of the cell becomes unresponsive, its +primary router knows that there exists backup routers in the cell. +After that it will start using the first backup router sent in the +packet as router of that cell. In this case the backup router must +notify its new primary router about the servers, channels and clients +it has connected to it. The primary router knows that this server +has become a router of the cell because of failure of the primary +router in the cell. It must also cope with the fact that the servers, +channels and clients that the new backup router announces are not +really new, since they used to exist in the primary router of the +cell. + +It is required that other normal servers has passive connections to +the backup router(s) in the cell. Some keepalive actions may be needed +by the server to keep the connection alive. After they notice the +failure of the primary router they must start using the connection to +the first backup router as their primary route. + +It is recommended that there would be at least one backup router in +the cell. It is not recommended to have all servers in the cell acting +as backup routers as it requires establishing several connections to +several servers in the cell. Large cells can easily have several +backup routers in the cell. The order of the backup routers are decided +at the primary router of the cell and servers and backup servers in the +cell must be configured accordingly. It is not required that the backup +server is actually active server in the cell. Backup router may be spare +server in the cell that does not accept normal client connections at all. +It maybe reserved purely for the backup purposes. These, however, are +cell management issues. + +If the first backup router is down as well and there is another backup +router in the cell then it will start acting as the primary router as +described above. + + .ti 0 3. SILC Specification diff --git a/lib/silccore/silcnotify.h b/lib/silccore/silcnotify.h index 8aa9d580..9f25eded 100644 --- a/lib/silccore/silcnotify.h +++ b/lib/silccore/silcnotify.h @@ -43,6 +43,7 @@ typedef unsigned short SilcNotifyType; #define SILC_NOTIFY_TYPE_CHANNEL_CHANGE 10 /* Channel's ID has changed */ #define SILC_NOTIFY_TYPE_SERVER_SIGNOFF 11 /* Server quitting SILC */ #define SILC_NOTIFY_TYPE_KICKED 12 /* Kicked from channel */ +#define SILC_NOTIFY_TYPE_KILLED 13 /* Killed from the network */ /* Prototypes */ SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer); diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index e3f98a52..7d1b11ba 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -219,6 +219,7 @@ typedef int (*SilcPacketCheckDecrypt)(SilcPacketType packet_type, #define SILC_PACKET_REKEY_DONE 23 /* Re-key done */ #define SILC_PACKET_HEARTBEAT 24 /* Heartbeat */ #define SILC_PACKET_KEY_AGREEMENT 25 /* Key Agreement request */ +#define SILC_PACKET_CELL_ROUTERS 26 /* Cell routers backup */ #define SILC_PACKET_PRIVATE 200 /* Private range start */ #define SILC_PACKET_MAX 255 /* RESERVED */ -- 2.24.0