From 18774fe934132c6e5376757e63e43ac3f3b22577 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 18 Jun 2002 17:09:22 +0000 Subject: [PATCH] Fixed founder mode chaning in JOIN and CUMODE_CHANGE notifys. Close all connections and listeners in silc_server_stop. --- CHANGES | 17 ++++++++ TODO | 4 -- apps/silcd/command.c | 33 ++++++++++---- apps/silcd/packet_receive.c | 83 ++++++++++++++++++------------------ apps/silcd/packet_send.c | 6 +-- apps/silcd/server.c | 34 ++++++++++++--- apps/silcd/server_internal.h | 22 +++++----- lib/silcclient/client.c | 5 +++ lib/silcutil/silcsockconn.h | 6 ++- 9 files changed, 137 insertions(+), 73 deletions(-) diff --git a/CHANGES b/CHANGES index 58b2428c..1edc1a5e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,20 @@ +Tue Jun 18 17:14:52 EEST 2002 Pekka Riikonen + + * When authenticating as founder during JOIN command, check + that the one authenticating becomes the only founder on the + channel. Affected file silcd/command.c. + + * Better checking for founder mode setting when CUMODE_CHANGE + notify is received. Affected file silcd/packet_receive.c. + + * Close all connections when shutting down the server by sending + DISCONNECT packet. Close all listeners too when shutting + down the server. Affected file silcd/server.c. + + * Handle DISCONNECT packet correctly in client library by + calling the "disconnect" client operation. Affected file + lib/silcclient/client.c. + Tue Jun 18 10:26:27 EEST 2002 Pekka Riikonen * The log file is not dupped internally anymore in diff --git a/TODO b/TODO index 5b9372be..6748473e 100644 --- a/TODO +++ b/TODO @@ -19,10 +19,6 @@ TODO/bugs In SILC Client Library TODO/bugs In SILC Server ======================== - o Make the "one founder per channel" check during join -founder as well. - - o Make the "one founder per channel" during CUMODE notify as well. - o Implement the and the Attribute Payload to the core library, client and server. Maybe implementations of RFC 2425 and RFC 2426 to make it complete. diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 14d50d2d..50d620a2 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -3220,6 +3220,8 @@ static void silc_server_command_join_channel(SilcServer server, */ if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { SilcIDListData idata = (SilcIDListData)client; + SilcChannelClientEntry chl2; + SilcHashTableList htl; if (channel->founder_key && idata->public_key && silc_pkcs_public_key_compare(channel->founder_key, @@ -3228,6 +3230,19 @@ static void silc_server_command_join_channel(SilcServer server, if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY, channel->founder_key, 0, server->sha1hash, client->id, SILC_ID_CLIENT)) { + + /* There cannot be anyone else as founder on the channel now. This + client is definitely the founder due to this authentication */ + silc_hash_table_list(channel->user_list, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&chl2)) + if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) { + chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO; + silc_server_force_cumode_change(server, NULL, channel, chl2, + chl2->mode); + break; + } + silc_hash_table_list_reset(&htl); + umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO); founder = TRUE; } @@ -3415,6 +3430,7 @@ static void silc_server_command_join_channel(SilcServer server, we'll ignore it (in packet_receive.c) so we must send it here. If we are router then this will send it to local clients and local servers. */ + SILC_LOG_DEBUG(("Send JOIN notify to channel")); silc_server_send_notify_to_channel(server, NULL, channel, FALSE, SILC_NOTIFY_TYPE_JOIN, 2, clidp->data, clidp->len, @@ -3443,22 +3459,23 @@ static void silc_server_command_join_channel(SilcServer server, notify the mode change to the channel. */ if (founder) { SILC_PUT32_MSB(chl->mode, mode); + SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel")); silc_server_send_notify_to_channel(server, NULL, channel, FALSE, SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4, clidp->data, clidp->len, mode, 4, clidp->data, clidp->len, fkey, fkey_len); - - /* Set CUMODE notify type to network */ - if (!server->standalone) - silc_server_send_notify_cumode(server, server->router->connection, - server->server_type == SILC_ROUTER ? - TRUE : FALSE, channel, - chl->mode, client->id, SILC_ID_CLIENT, - client->id, channel->founder_key); } } + /* Set CUMODE notify type to network */ + if (founder && !server->standalone) + silc_server_send_notify_cumode(server, server->router->connection, + server->server_type == SILC_ROUTER ? + TRUE : FALSE, channel, + chl->mode, client->id, SILC_ID_CLIENT, + client->id, channel->founder_key); + silc_buffer_free(reply); silc_buffer_free(clidp); silc_buffer_free(chidp); diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index bd9545f8..1c71e7e6 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -786,40 +786,21 @@ void silc_server_notify(SilcServer server, } } - /* Get target channel entry */ + /* Get target channel user entry */ if (!silc_server_client_on_channel(client2, channel, &chl)) goto out; if (mode & SILC_CHANNEL_UMODE_CHANFO && - !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && !client && - server->server_type == SILC_ROUTER) { - /* Get the founder of the channel and if found then this client - cannot be the founder since there already is one. */ - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chl2)) - if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) { - mode &= ~SILC_CHANNEL_UMODE_CHANFO; - silc_server_force_cumode_change(server, sock, channel, chl, mode); - notify_sent = TRUE; - break; - } - silc_hash_table_list_reset(&htl); - if (!(mode & SILC_CHANNEL_UMODE_CHANFO)) - break; - } - - if (client && mode & SILC_CHANNEL_UMODE_CHANFO && - !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) && - server->server_type == SILC_ROUTER) { - /* Check whether this client is allowed to be channel founder on - this channel. */ + !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) && + server->server_type == SILC_ROUTER && + sock->user_data != server->router) { SilcPublicKey founder_key = NULL; /* If channel doesn't have founder auth mode then it's impossible that someone would be getting founder rights with CUMODE command. In that case there already either is founder or there isn't founder at all on the channel. */ - if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) { + if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) { /* Force the mode to not have founder mode */ mode &= ~SILC_CHANNEL_UMODE_CHANFO; silc_server_force_cumode_change(server, sock, channel, chl, mode); @@ -833,7 +814,8 @@ void silc_server_notify(SilcServer server, while (silc_hash_table_get(&htl, NULL, (void *)&chl2)) if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) { mode &= ~SILC_CHANNEL_UMODE_CHANFO; - silc_server_force_cumode_change(server, sock, channel, chl, mode); + silc_server_force_cumode_change(server, sock, channel, + chl, mode); notify_sent = TRUE; break; } @@ -855,28 +837,47 @@ void silc_server_notify(SilcServer server, break; } - /* Now match the public key we have cached and public key sent. - They must match. */ - if (client->data.public_key && - !silc_pkcs_public_key_compare(channel->founder_key, - client->data.public_key)) { - mode &= ~SILC_CHANNEL_UMODE_CHANFO; - silc_server_force_cumode_change(server, sock, channel, chl, mode); - notify_sent = TRUE; - break; - } - if (!silc_pkcs_public_key_compare(channel->founder_key, - founder_key)) { - mode &= ~SILC_CHANNEL_UMODE_CHANFO; - silc_server_force_cumode_change(server, sock, channel, chl, mode); - notify_sent = TRUE; - break; + if (channel->founder_key) { + /* Now match the public key we have cached and public key sent. + They must match. */ + if (client && client->data.public_key && + !silc_pkcs_public_key_compare(channel->founder_key, + client->data.public_key)) { + mode &= ~SILC_CHANNEL_UMODE_CHANFO; + silc_server_force_cumode_change(server, sock, channel, chl, mode); + notify_sent = TRUE; + break; + } + if (!silc_pkcs_public_key_compare(channel->founder_key, + founder_key)) { + mode &= ~SILC_CHANNEL_UMODE_CHANFO; + silc_server_force_cumode_change(server, sock, channel, chl, mode); + notify_sent = TRUE; + break; + } } + /* There cannot be anyone else as founder on the channel now. This + client is definitely the founder due to this authentication */ + silc_hash_table_list(channel->user_list, &htl); + while (silc_hash_table_get(&htl, NULL, (void *)&chl2)) + if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) { + chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO; + silc_server_force_cumode_change(server, NULL, channel, chl2, + chl2->mode); + break; + } + silc_hash_table_list_reset(&htl); + if (founder_key) silc_pkcs_public_key_free(founder_key); } + if (server->server_type == SILC_ROUTER && chl->mode == mode) { + SILC_LOG_DEBUG(("Mode is changed already")); + break; + } + SILC_LOG_DEBUG(("Changing the channel user mode")); /* Change the mode */ diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 512ee423..737da431 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -173,9 +173,9 @@ void silc_server_packet_send_dest(SilcServer server, /* Set the packet context pointers */ packetdata.type = type; packetdata.flags = flags; - packetdata.src_id = silc_id_id2str(server->id, server->id_type); - packetdata.src_id_len = silc_id_get_len(server->id, server->id_type); - packetdata.src_id_type = server->id_type; + packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER); + packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER); + packetdata.src_id_type = SILC_ID_SERVER; packetdata.dst_id = dst_id_data; packetdata.dst_id_len = dst_id_len; packetdata.dst_id_type = dst_id_type; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 0f3e2da5..93e81034 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -167,6 +167,7 @@ bool silc_server_init_secondary(SilcServer server) silc_socket_alloc(sock_list[sock], SILC_SOCKET_TYPE_SERVER, NULL, &newsocket); server->sockets[sock_list[sock]] = newsocket; + SILC_SET_LISTENER(newsocket); /* Perform name and address lookups to resolve the listenning address and port. */ @@ -310,6 +311,7 @@ bool silc_server_init(SilcServer server) is sent as argument for fast referencing in the future. */ silc_socket_alloc(sock, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket); server->sockets[sock] = newsocket; + SILC_SET_LISTENER(newsocket); /* Perform name and address lookups to resolve the listenning address and port. */ @@ -336,7 +338,6 @@ bool silc_server_init(SilcServer server) server->id = id; server->id_string = silc_id_id2str(id, SILC_ID_SERVER); server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER); - server->id_type = SILC_ID_SERVER; server->server_name = server->config->server_info->server_name; server->config->server_info->server_name = NULL; @@ -577,17 +578,31 @@ void silc_server_stop(SilcServer server) if (server->schedule) { int i; + /* Close all connections */ for (i = 0; i < server->config->param.connections_max; i++) { if (!server->sockets[i]) continue; - silc_socket_free(server->sockets[i]); + if (!SILC_IS_LISTENER(server->sockets[i])) { + silc_schedule_task_del_by_context(server->schedule, + server->sockets[i]); + silc_server_disconnect_remote(server, server->sockets[i], + SILC_STATUS_OK, + "Server is shutting down"); + } else { + silc_socket_free(server->sockets[i]); + server->sockets[i] = NULL; + } } - silc_free(server->sockets); - server->sockets = NULL; + + /* We are not connected to network anymore */ + server->standalone = TRUE; silc_schedule_stop(server->schedule); silc_schedule_uninit(server->schedule); server->schedule = NULL; + + silc_free(server->sockets); + server->sockets = NULL; } silc_server_protocols_unregister(); @@ -1230,6 +1245,14 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock, sock->ip)); /* Listenning port */ + if (!server->sockets[(SilcUInt32)proto_ctx->context]) { + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_RESOURCE_LIMIT, + "Connection refused"); + server->stat.conn_failures++; + silc_free(proto_ctx); + return; + } port = server->sockets[(SilcUInt32)proto_ctx->context]->port; /* Check whether this connection is denied to connect to us. */ @@ -2057,7 +2080,8 @@ void silc_server_packet_parse_type(SilcServer server, status = (SilcStatus)packet->buffer->data[0]; if (packet->buffer->len > 1 && silc_utf8_valid(packet->buffer->data + 1, packet->buffer->len - 1)) - message = silc_memdup(packet->buffer->data, packet->buffer->len); + message = silc_memdup(packet->buffer->data + 1, + packet->buffer->len - 1); SILC_LOG_ERROR(("Disconnected by %s (%s): %s (%d) %s", sock->ip, sock->hostname, diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 7b27b6c3..f0984f40 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -65,28 +65,28 @@ typedef struct { */ struct SilcServerStruct { char *server_name; - int server_type; int sock; + SilcServerEntry id_entry; SilcServerID *id; unsigned char *id_string; SilcUInt32 id_string_len; - SilcIdType id_type; - SilcUInt32 starttime; - bool standalone; /* TRUE if server is standalone, and + + unsigned int server_type : 2; /* Server type (server.h) */ + unsigned int standalone : 1; /* Set if server is standalone, and does not have connection to network. */ - bool listenning; /* TRUE if server is listenning for + unsigned int listenning : 1; /* Set if server is listenning for incoming connections. */ - bool background; - SilcServerEntry id_entry; /* Server's own ID entry */ + unsigned int background : 1; /* Set when server is on background */ + unsigned int backup_router : 1; /* Set if this is backup router */ + unsigned int backup_primary : 1; /* Set if we've switched our primary + router to a backup router. */ + SilcServerEntry router; /* Pointer to the primary router */ unsigned long router_connect; /* Time when router was connected */ - SilcServerBackup backup; /* Backup routers */ - bool backup_router; /* TRUE if this is backup router */ - bool backup_primary; /* TRUE if we've switched our primary - router to a backup router. */ SilcServerConnection router_conn; /* non-NULL when connecting to the primary router, and NULL otherwise. */ + SilcServerBackup backup; /* Backup routers */ /* Current command identifier, 0 not used */ SilcUInt16 cmd_ident; diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 59945b6e..f389f60d 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -1471,12 +1471,17 @@ void silc_client_close_connection(SilcClient client, SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later) { SilcClient client = (SilcClient)context; + SilcClientConnection conn; SilcSocketConnection sock; SILC_CLIENT_GET_SOCK(client, fd, sock); if (sock == NULL) return; + conn = (SilcClientConnection)sock->user_data; + if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT) + client->internal->ops->disconnect(client, conn); + silc_client_close_connection_real(client, sock, sock->user_data); } diff --git a/lib/silcutil/silcsockconn.h b/lib/silcutil/silcsockconn.h index d7acdf95..a78f3939 100644 --- a/lib/silcutil/silcsockconn.h +++ b/lib/silcutil/silcsockconn.h @@ -101,6 +101,7 @@ typedef enum { #define SILC_SF_HOST_LOOKUP 5 /* performing host lookup for socket */ #define SILC_SF_DISABLED 6 /* socket connection is disabled, no data is sent or received. */ +#define SILC_SF_LISTENER 7 /****s* silcutil/SilcSocketConnectionAPI/SilcSocketConnectionStruct * @@ -215,13 +216,15 @@ struct SilcSocketConnectionStruct { #define SILC_SET_DISCONNECTING(x) SF_SET((x), SILC_SF_DISCONNECTING) #define SILC_SET_DISCONNECTED(x) SF_SET((x), SILC_SF_DISCONNECTED) #define SILC_SET_HOST_LOOKUP(x) SF_SET((x), SILC_SF_HOST_LOOKUP) -#define SILC_SET_DISABLED(x) SF_SET((x), SILC_SF_HOST_LOOKUP) +#define SILC_SET_DISABLED(x) SF_SET((x), SILC_SF_DISABLED) +#define SILC_SET_LISTENER(x) SF_SET((x), SILC_SF_LISTENER) #define SILC_UNSET_OUTBUF_PENDING(x) SF_UNSET((x), SILC_SF_OUTBUF_PENDING) #define SILC_UNSET_INBUF_PENDING(x) SF_UNSET((x), SILC_SF_INBUF_PENDING) #define SILC_UNSET_DISCONNECTING(x) SF_UNSET((x), SILC_SF_DISCONNECTING) #define SILC_UNSET_DISCONNECTED(x) SF_UNSET((x), SILC_SF_DISCONNECTED) #define SILC_UNSET_HOST_LOOKUP(x) SF_UNSET((x), SILC_SF_HOST_LOOKUP) #define SILC_UNSET_DISABLED(x) SF_UNSET((x), SILC_SF_DISABLED) +#define SILC_UNSET_LISTENER(x) SF_UNSET((x), SILC_SF_LISTENER) /* Checking for flags */ #define SILC_IS_OUTBUF_PENDING(x) SF_IS((x), SILC_SF_OUTBUF_PENDING) @@ -230,6 +233,7 @@ struct SilcSocketConnectionStruct { #define SILC_IS_DISCONNECTED(x) SF_IS((x), SILC_SF_DISCONNECTED) #define SILC_IS_HOST_LOOKUP(x) SF_IS((x), SILC_SF_HOST_LOOKUP) #define SILC_IS_DISABLED(x) SF_IS((x), SILC_SF_DISABLED) +#define SILC_IS_LISTENER(x) SF_IS((x), SILC_SF_LISTENER) /* Prototypes */ -- 2.24.0