silcd: handle SIGNOFF notify for local clients correctly
authorPekka Riikonen <priikone@silcnet.org>
Fri, 27 Feb 2009 14:16:11 +0000 (16:16 +0200)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 27 Feb 2009 14:16:11 +0000 (16:16 +0200)
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.

apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server_internal.h
apps/silcd/silcd.c

index 2d9ce41f874227a35d55f8248abfb8a5c5978066..f2a822124a2560c7dfc39d60e84e122bb083f2c4 100644 (file)
@@ -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;
index 9fb4aaf3acb9e1ff9142fc8341c7b38011921d78..e18c7de0c4674804e4b5d5b0fc2235f2cc223acb 100644 (file)
@@ -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,
index 09257e66465a415a1d0f281a0b4e635348e8f3da..64cca8169cc9e216e5d8836cd9652a9787f8598f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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
index d367328c6578fdb15942f922e108a2fc7525e4de..3d4db10eab7133df3875aa3393dbdbe5358f3777 100644 (file)
@@ -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*" },