Merge branch 'topic/detach-fixes' of git://valera-ext.nynaeve.net/silc into silc...
[silc.git] / apps / silcd / server.c
index c2df082c61118703639b85fca1f9ad34de233bfd..2f97d79d837aaeee25893ad676f2f5cd1dab382d 100644 (file)
@@ -233,7 +233,10 @@ SILC_TASK_CALLBACK(silc_server_packet_error_timeout)
 
   if (server->router_conn && server->router_conn->sock == stream &&
       !server->router && server->standalone) {
+    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);
   } else {
     /* If backup disconnected then mark that resuming will not be allowed */
      if (server->server_type == SILC_ROUTER && !server->backup_router &&
@@ -280,9 +283,14 @@ static void silc_server_packet_error(SilcPacketEngine engine,
   if (!silc_packet_stream_is_valid(stream))
     return;
 
+  /* In case we get here many times, register only one timeout */
+  silc_schedule_task_del_by_all(server->schedule, 0,
+                               silc_server_packet_error_timeout, stream);
+
+  /* Close connection with random timeout */
   silc_schedule_task_add_timeout(server->schedule,
-                                silc_server_packet_error_timeout,
-                                stream, 0, 0);
+                                silc_server_packet_error_timeout, stream,
+                                silc_rng_get_byte(server->rng) % 10, 0);
 }
 
 /* Packet stream callbacks */
@@ -704,6 +712,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();
@@ -1608,7 +1617,6 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
   SilcConnAuth connauth;
   SilcCipher send_key, receive_key;
   SilcHmac hmac_send, hmac_receive;
-  SilcHash hash;
 
   server = entry->server;
   sconn = entry->data.sconn;
@@ -1644,7 +1652,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 */
@@ -1798,6 +1806,8 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
   }
   entry->server = server;
   entry->data.sconn = sconn;
+  entry->data.conn_type = SILC_CONN_UNKNOWN;
+  entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
   silc_packet_set_context(sconn->sock, entry);
 
   SILC_LOG_DEBUG(("Created unknown connection %p", entry));
@@ -2686,9 +2696,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++;
@@ -2899,6 +2911,18 @@ static void silc_server_rekey_completion(SilcSKE ske,
                                 sock, idata->sconn->rekey_timeout, 0);
 }
 
+/* Helper to stop future rekeys on a link. */
+void silc_server_stop_rekey(SilcServer server, SilcClientEntry client)
+{
+  if (!client->connection)
+    return;
+
+  SILC_LOG_DEBUG(("Stopping rekey for client %p", client));
+
+  silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
+                               client->connection);
+}
+
 /* Rekey callback.  Start rekey as initiator */
 
 SILC_TASK_CALLBACK(silc_server_do_rekey)
@@ -2911,7 +2935,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 */
@@ -2975,6 +2999,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));
@@ -3122,6 +3151,7 @@ void silc_server_free_client_data(SilcServer server,
 
   /* Update statistics */
   server->stat.my_clients--;
+  SILC_VERIFY(server->stat.clients > 0);
   server->stat.clients--;
   if (server->stat.cell_clients)
     server->stat.cell_clients--;