Assert that the client count is positive prior to decrementing it.
[silc.git] / apps / silcd / server.c
index 52bc4b702779e89c6caf873c2cfa3e9cce345fc6..5b655419693626fbce7bd382641c8292b2c52be4 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "serverincludes.h"
 #include "server_internal.h"
+#include <assert.h>
 
 /************************* Types and definitions ****************************/
 
@@ -201,7 +202,7 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
 
   if (server->router_conn && server->router_conn->sock == stream &&
       !server->router && server->standalone) {
-    if (idata->sconn->callback)
+    if (idata->sconn && idata->sconn->callback)
       (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     silc_server_create_connections(server);
     silc_server_free_sock_user_data(server, stream, NULL);
@@ -214,7 +215,7 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
         server->backup_closed = TRUE;
     }
 
-    if (idata->sconn->callback)
+    if (idata->sconn && idata->sconn->callback)
       (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     silc_server_free_sock_user_data(server, stream, NULL);
   }
@@ -243,7 +244,7 @@ SILC_TASK_CALLBACK(silc_server_packet_error_timeout)
         server->backup_closed = TRUE;
     }
 
-    if (idata->sconn->callback)
+    if (idata->sconn && idata->sconn->callback)
       (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     silc_server_free_sock_user_data(server, stream, NULL);
   }
@@ -704,6 +705,7 @@ void silc_server_free(SilcServer server)
   silc_free(server->local_list);
   silc_free(server->global_list);
   silc_free(server->server_name);
+  silc_free(server->id);
   silc_free(server);
 
   silc_hmac_unregister_all();
@@ -766,6 +768,7 @@ SilcBool silc_server_init(SilcServer server)
   SilcNetListener listener;
   SilcUInt16 *port;
   char **ip;
+  char *external_ip;
 
   SILC_LOG_DEBUG(("Initializing server"));
 
@@ -869,8 +872,11 @@ SilcBool silc_server_init(SilcServer server)
   /* Create a Server ID for the server. */
   port = silc_net_listener_get_port(listener, NULL);
   ip = silc_net_listener_get_ip(listener, NULL);
-  silc_id_create_server_id(server->config->server_info->primary->public_ip ?
-                          server->config->server_info->primary->public_ip :
+  external_ip = server->config->server_info->external_ip ?
+               server->config->server_info->external_ip :
+               server->config->server_info->primary->public_ip;
+  silc_id_create_server_id(external_ip ?
+                          external_ip :
                           ip[0], port[0], server->rng, &id);
   if (!id)
     goto err;
@@ -1599,21 +1605,23 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
 {
   SilcPacketStream sock = context;
   SilcUnknownEntry entry = silc_packet_get_context(sock);
-  SilcServerConnection sconn = entry->data.sconn;
-  SilcServer server = entry->server;
-  SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
+  SilcServerConnection sconn;
+  SilcServer server;
+  SilcServerConfigRouter *conn;
   SilcAuthMethod auth_meth = SILC_AUTH_NONE;
   void *auth_data = NULL;
   SilcUInt32 auth_data_len = 0;
   SilcConnAuth connauth;
   SilcCipher send_key, receive_key;
   SilcHmac hmac_send, hmac_receive;
-  SilcHash hash;
-
-  SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
 
+  server = entry->server;
+  sconn = entry->data.sconn;
+  conn = sconn->conn.ref_ptr;
   entry->op = NULL;
 
+  SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
+
   if (status != SILC_SKE_STATUS_OK) {
     /* SKE failed */
     SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
@@ -1641,7 +1649,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
 
   /* Set the keys into use.  The data will be encrypted after this. */
   if (!silc_ske_set_keys(ske, keymat, prop, &send_key, &receive_key,
-                        &hmac_send, &hmac_receive, &hash)) {
+                        &hmac_send, &hmac_receive, NULL)) {
     silc_ske_free(ske);
 
     /* Try reconnecting if configuration wants it */
@@ -2683,9 +2691,11 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
   idata->rekey = rekey;
   idata->public_key = silc_pkcs_public_key_copy(prop->public_key);
   pk = silc_pkcs_public_key_encode(idata->public_key, &pk_len);
-  silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint);
-
-  silc_hash_alloc(silc_hash_get_name(prop->hash), &idata->hash);
+  if (pk) {
+    silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint);
+    silc_free(pk);
+  }
+  idata->hash = hash;
 
   SILC_LOG_DEBUG(("Starting connection authentication"));
   server->stat.auth_attempts++;
@@ -2818,6 +2828,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
   entry->port = port;
   entry->server = server;
   entry->data.conn_type = SILC_CONN_UNKNOWN;
+  entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
   silc_packet_set_context(packet_stream, entry);
 
   SILC_LOG_DEBUG(("Created unknown connection %p", entry));
@@ -2907,7 +2918,7 @@ SILC_TASK_CALLBACK(silc_server_do_rekey)
   SILC_LOG_DEBUG(("Perform rekey, sock %p", sock));
 
   /* Do not execute rekey with disabled connections */
-  if (idata->status & SILC_IDLIST_STATUS_DISABLED)
+  if (idata->status & SILC_IDLIST_STATUS_DISABLED || !idata->rekey)
     return;
 
   /* If another protocol is active do not start rekey */
@@ -2971,6 +2982,11 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
   SilcIDListData idata = silc_packet_get_context(sock);
   SilcSKE ske;
 
+  if (!idata->rekey) {
+    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,
                  SILC_CONNTYPE_STRING(idata->conn_type), sock));
@@ -3118,6 +3134,7 @@ void silc_server_free_client_data(SilcServer server,
 
   /* Update statistics */
   server->stat.my_clients--;
+  assert(server->stat.clients > 0);
   server->stat.clients--;
   if (server->stat.cell_clients)
     server->stat.cell_clients--;