From: Pekka Riikonen Date: Fri, 27 Feb 2009 14:16:11 +0000 (+0200) Subject: silcd: handle SIGNOFF notify for local clients correctly X-Git-Tag: silc.server.1.1.16~4 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=f17f0003337914b58ced7b318ce8455ffc2a9e51 silcd: handle SIGNOFF notify for local clients correctly In some rare cases router can send SIGNOFF notify to server for a client that is locally connected to the server. The server didn't close the client's connection but freed the entry. This later caused various different crashes when accessing the freed the client. --- diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 2d9ce41f..f2a82212 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -361,6 +361,20 @@ static void silc_server_notify_process(SilcServer server, /* Remove this client from watcher list if it is */ silc_server_del_from_watcher_list(server, client); + /* It's possible router doesn't accept our local client in the network + and sends SIGNOFF to our local client */ + if (SILC_IS_LOCAL(client)) { + SILC_LOG_DEBUG(("SIGNOFF from router to local client, disconnect")); + if (client->data.sconn) { + silc_server_connection_free(client->data.sconn); + client->data.sconn = NULL; + } + silc_packet_set_context(client->connection, NULL); + silc_server_disconnect_remote(server, client->connection, + SILC_STATUS_ERR_RESOURCE_LIMIT, + "Router prevented registration"); + } + client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; client->mode = 0; client->router = NULL; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 9fb4aaf3..e18c7de0 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -2627,6 +2627,8 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, /* Add connection to server->conns so that we know we have connection to this peer. */ sconn = silc_calloc(1, sizeof(*sconn)); + if (!sconn) + goto out; sconn->server = server; sconn->sock = sock; sconn->remote_host = strdup(hostname); @@ -3020,6 +3022,10 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock, silc_packet_free(packet); return; } + if (idata->conn_type == SILC_CONN_UNKNOWN) { + silc_packet_free(packet); + return; + } SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s], sock %p", idata->sconn->remote_host, idata->sconn->remote_port, diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 09257e66..64cca816 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2009 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -216,5 +216,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router); SILC_TASK_CALLBACK(silc_server_connect_to_router_retry); void silc_server_watcher_list_destroy(void *key, void *context, void *user_context); +void silc_server_connection_free(SilcServerConnection sconn); #endif diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index d367328c..3d4db10e 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -462,7 +462,7 @@ static DebugLevel debug_levels[] = { { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" }, /* All basic stuff from silcd/ */ - { 10, "silc_server_*" }, + { 10, "silc_server_*,*silc_id_create_*" }, /* All from silcd/ */ { 15, "*silcd*,*serverid*,silc_server_*,*idlist*" },