updates.
[silc.git] / apps / silcd / server.c
index b56817765c41e3e86e58410189dbf60c0e75f38d..ef90e6dc1d731083a5b6ba1072f510afd2974168 100644 (file)
@@ -145,10 +145,14 @@ int silc_server_init(SilcServer server)
   silc_server_config_setlogfiles(server->config);
  
   /* Register all configured ciphers, PKCS and hash functions. */
-  silc_server_config_register_ciphers(server->config);
-  silc_server_config_register_pkcs(server->config);
-  silc_server_config_register_hashfuncs(server->config);
-  silc_server_config_register_hmacs(server->config);
+  if (!silc_server_config_register_ciphers(server->config))
+    silc_cipher_register_default();
+  if (!silc_server_config_register_pkcs(server->config))
+    silc_pkcs_register_default();
+  if (!silc_server_config_register_hashfuncs(server->config))
+    silc_hash_register_default();
+  if (!silc_server_config_register_hmacs(server->config))
+    silc_hmac_register_default();
 
   /* Initialize random number generator for the server. */
   server->rng = silc_rng_alloc();
@@ -479,6 +483,8 @@ void silc_server_run(SilcServer server)
 {
   SILC_LOG_DEBUG(("Running server"));
 
+  SILC_LOG_INFO(("SILC Server started"));
+
   /* Start the scheduler, the heart of the SILC server. When this returns
      the program will be terminated. */
   silc_schedule();
@@ -599,7 +605,7 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
   SILC_REGISTER_CONNECTION_FOR_IO(sock);
   
   /* Run the protocol */
-  protocol->execute(server->timeout_queue, 0, protocol, sock, 0, 0);
+  silc_protocol_execute(protocol, server->timeout_queue, 0, 0);
 }
   
 /* This function connects to our primary router or if we are a router this
@@ -688,7 +694,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     (SilcServerKEInternalContext *)protocol->context;
   SilcServer server = (SilcServer)ctx->server;
   SilcServerConnection sconn = (SilcServerConnection)ctx->context;
-  SilcSocketConnection sock = server->sockets[fd];
+  SilcSocketConnection sock = ctx->sock;
   SilcServerConnAuthInternalContext *proto_ctx;
   SilcServerConfigSectionServerConnection *conn = NULL;
 
@@ -809,8 +815,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
                       SILC_TASK_PRI_LOW);
 
   /* Run the protocol */
-  sock->protocol->execute(server->timeout_queue, 0, 
-                         sock->protocol, sock->sock, 0, 0);
+  silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 0);
 }
 
 /* Finalizes the connection to router. Registers a server task to the
@@ -1005,6 +1010,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
      later when outgoing data is available. */
   SILC_REGISTER_CONNECTION_FOR_IO(sock);
 
+  SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
+                newsocket->ip));
+
   port = server->sockets[fd]->port; /* Listenning port */
 
   /* Check whether this connection is denied to connect to us. */
@@ -1014,6 +1022,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
                                          port);
   if (deny) {
     /* The connection is denied */
+    SILC_LOG_INFO(("Connection %s (%s) is denied", 
+                   newsocket->hostname, newsocket->ip));
     silc_server_disconnect_remote(server, newsocket, deny->comment ?
                                  deny->comment :
                                  "Server closed connection: "
@@ -1051,9 +1061,6 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
 
   /* The connection is allowed */
 
-  SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
-                newsocket->ip));
-
   /* Allocate internal context for key exchange protocol. This is
      sent as context for the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
@@ -1098,7 +1105,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
   SilcServerKEInternalContext *ctx = 
     (SilcServerKEInternalContext *)protocol->context;
   SilcServer server = (SilcServer)ctx->server;
-  SilcSocketConnection sock = server->sockets[fd];
+  SilcSocketConnection sock = ctx->sock;
   SilcServerConnAuthInternalContext *proto_ctx;
 
   SILC_LOG_DEBUG(("Start"));
@@ -1648,10 +1655,8 @@ void silc_server_packet_parse_type(SilcServer server,
     SILC_LOG_DEBUG(("Success packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
-    if (sock->protocol) {
-      sock->protocol->execute(server->timeout_queue, 0,
-                             sock->protocol, sock->sock, 0, 0);
-    }
+    if (sock->protocol)
+      silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 0);
     break;
 
   case SILC_PACKET_FAILURE:
@@ -1789,8 +1794,7 @@ void silc_server_packet_parse_type(SilcServer server,
       proto_ctx->packet = silc_packet_context_dup(packet);
 
       /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock, 0, 100000);
+      silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 100000);
     } else {
       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -1818,8 +1822,7 @@ void silc_server_packet_parse_type(SilcServer server,
        proto_ctx->packet = silc_packet_context_dup(packet);
 
        /* Let the protocol handle the packet */
-       sock->protocol->execute(server->timeout_queue, 0, 
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 0);
       } else {
        SilcServerKEInternalContext *proto_ctx = 
          (SilcServerKEInternalContext *)sock->protocol->context;
@@ -1835,9 +1838,8 @@ void silc_server_packet_parse_type(SilcServer server,
          break;
 
        /* Let the protocol handle the packet */
-       sock->protocol->execute(server->timeout_queue, 0, 
-                               sock->protocol, sock->sock,
-                               0, 100000);
+       silc_protocol_execute(sock->protocol, server->timeout_queue, 
+                             0, 100000);
       }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
@@ -1864,8 +1866,7 @@ void silc_server_packet_parse_type(SilcServer server,
        proto_ctx->packet = silc_packet_context_dup(packet);
 
        /* Let the protocol handle the packet */
-       sock->protocol->execute(server->timeout_queue, 0, 
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 0);
       } else {
        SilcServerKEInternalContext *proto_ctx = 
          (SilcServerKEInternalContext *)sock->protocol->context;
@@ -1881,9 +1882,8 @@ void silc_server_packet_parse_type(SilcServer server,
          break;
 
        /* Let the protocol handle the packet */
-       sock->protocol->execute(server->timeout_queue, 0, 
-                               sock->protocol, sock->sock,
-                               0, 100000);
+       silc_protocol_execute(sock->protocol, server->timeout_queue, 
+                             0, 100000);
       }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
@@ -1923,8 +1923,7 @@ void silc_server_packet_parse_type(SilcServer server,
       proto_ctx->packet = silc_packet_context_dup(packet);
 
       /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock, 0, 0);
+      silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 0);
     } else {
       SILC_LOG_ERROR(("Received Connection Auth packet but no authentication "
                      "protocol active, packet dropped."));
@@ -2031,8 +2030,7 @@ void silc_server_packet_parse_type(SilcServer server,
       proto_ctx->packet = silc_packet_context_dup(packet);
 
       /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock, 0, 0);
+      silc_protocol_execute(sock->protocol, server->timeout_queue, 0, 0);
     } else {
       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
                      "protocol active, packet dropped."));
@@ -2082,6 +2080,14 @@ void silc_server_close_connection(SilcServer server,
                  sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
                  "Router"), sock->sock));
 
+  /* If any protocol is active cancel its execution */
+  if (sock->protocol) {
+    silc_protocol_cancel(sock->protocol, server->timeout_queue);
+    sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+    silc_protocol_execute_final(sock->protocol, server->timeout_queue);
+    sock->protocol = NULL;
+  }
+
   /* We won't listen for this connection anymore */
   silc_schedule_unset_listen_fd(sock->sock);
 
@@ -2408,7 +2414,8 @@ int silc_server_remove_clients_by_server(SilcServer server,
     SilcBuffer args;
 
     /* Send SERVER_SIGNOFF notify to our primary router */
-    if (!server->standalone && server->router) {
+    if (!server->standalone && server->router &&
+       server->router != entry) {
       args = silc_argument_payload_encode(1, argv, argv_lens,
                                          argv_types);
       silc_server_send_notify_args(server, 
@@ -2508,27 +2515,8 @@ void silc_server_remove_from_channels(SilcServer server,
     /* Remove channel if there is no users anymore */
     if (server->server_type == SILC_ROUTER &&
        silc_hash_table_count(channel->user_list) < 2) {
-
       if (channel->rekey)
        silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
-
-      if (channel->founder_key) {
-       /* The founder auth data exists, do not remove the channel entry */
-       SilcChannelClientEntry chl2;
-       SilcHashTableList htl2;
-
-       channel->id = NULL;
-
-       silc_hash_table_list(channel->user_list, &htl2);
-       while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
-         silc_hash_table_del(chl2->client->channels, channel);
-         silc_hash_table_del(channel->user_list, chl2->client);
-         silc_free(chl2);
-       }
-       continue;
-      }
-
-      /* Remove the channel entry */
       if (!silc_idlist_del_channel(server->local_list, channel))
        silc_idlist_del_channel(server->global_list, channel);
       server->stat.my_channels--;
@@ -2737,14 +2725,23 @@ SILC_TASK_CALLBACK(silc_server_timeout_remote)
   SilcServer server = (SilcServer)context;
   SilcSocketConnection sock = server->sockets[fd];
 
+  SILC_LOG_DEBUG(("Start"));
+
   if (!sock)
     return;
 
+  /* If we have protocol active we must assure that we call the protocol's
+     final callback so that all the memory is freed. */
+  if (sock->protocol) {
+    sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+    silc_protocol_execute_final(sock->protocol, server->timeout_queue);
+    return;
+  }
+
   if (sock->user_data)
     silc_server_free_sock_user_data(server, sock);
 
-  silc_server_disconnect_remote(server, sock, 
-                               "Server closed connection: "
+  silc_server_disconnect_remote(server, sock, "Server closed connection: "
                                "Connection timeout");
 }
 
@@ -2791,6 +2788,8 @@ SilcChannelEntry silc_server_create_new_channel(SilcServer server,
                                  NULL, key, newhmac);
   if (!entry) {
     silc_free(channel_name);
+    silc_cipher_free(key);
+    silc_hmac_free(newhmac);
     return NULL;
   }
 
@@ -3306,7 +3305,9 @@ void silc_server_announce_get_channels(SilcServer server,
                                       SilcIDList id_list,
                                       SilcBuffer *channels,
                                       SilcBuffer *channel_users,
-                                      SilcBuffer *channel_users_modes)
+                                      SilcBuffer **channel_users_modes,
+                                      uint32 *channel_users_modes_c,
+                                      SilcChannelID ***channel_ids)
 {
   SilcIDCacheList list;
   SilcIDCacheEntry id_cache;
@@ -3315,6 +3316,7 @@ void silc_server_announce_get_channels(SilcServer server,
   uint32 id_len;
   uint16 name_len;
   int len;
+  int i = *channel_users_modes_c;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -3344,15 +3346,24 @@ void silc_server_announce_get_channels(SilcServer server,
                           SILC_STR_END);
        silc_buffer_pull(*channels, len);
 
+       *channel_users_modes = silc_realloc(*channel_users_modes,
+                                           sizeof(**channel_users_modes) * 
+                                           (i + 1));
+       (*channel_users_modes)[i] = NULL;
+       *channel_ids = silc_realloc(*channel_ids, 
+                                   sizeof(**channel_ids) * (i + 1));
+       (*channel_ids)[i] = NULL;
        silc_server_announce_get_channel_users(server, channel,
                                               channel_users,
-                                              channel_users_modes);
-
-       silc_free(cid);
+                                              channel_users_modes[i]);
+       (*channel_ids)[i] = channel->id;
+       i++;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
+
+      *channel_users_modes_c += i;
     }
 
     silc_idcache_list_free(list);
@@ -3365,19 +3376,26 @@ void silc_server_announce_get_channels(SilcServer server,
 
 void silc_server_announce_channels(SilcServer server)
 {
-  SilcBuffer channels = NULL, channel_users = NULL, channel_users_modes = NULL;
+  SilcBuffer channels = NULL, channel_users = NULL;
+  SilcBuffer *channel_users_modes = NULL;
+  uint32 channel_users_modes_c = 0;
+  SilcChannelID **channel_ids = NULL;
 
   SILC_LOG_DEBUG(("Announcing channels and channel users"));
 
   /* Get channels and channel users in local list */
   silc_server_announce_get_channels(server, server->local_list,
                                    &channels, &channel_users,
-                                   &channel_users_modes);
+                                   &channel_users_modes,
+                                   &channel_users_modes_c,
+                                   &channel_ids);
 
   /* Get channels and channel users in global list */
   silc_server_announce_get_channels(server, server->global_list,
                                    &channels, &channel_users,
-                                   &channel_users_modes);
+                                   &channel_users_modes,
+                                   &channel_users_modes_c,
+                                   &channel_ids);
 
   if (channels) {
     silc_buffer_push(channels, channels->data - channels->head);
@@ -3407,19 +3425,24 @@ void silc_server_announce_channels(SilcServer server)
   }
 
   if (channel_users_modes) {
-    silc_buffer_push(channel_users_modes, 
-                    channel_users_modes->data - channel_users_modes->head);
-    SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes->data, 
-                    channel_users_modes->len);
-
-    /* Send the packet */
-    silc_server_packet_send(server, server->router->connection,
-                           SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
-                           channel_users_modes->data, 
-                           channel_users_modes->len,
-                           FALSE);
-
-    silc_buffer_free(channel_users_modes);
+    int i;
+
+    for (i = 0; i < channel_users_modes_c; i++) {
+      silc_buffer_push(channel_users_modes[i], 
+                      channel_users_modes[i]->data - 
+                      channel_users_modes[i]->head);
+      SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes[i]->data, 
+                      channel_users_modes[i]->len);
+      silc_server_packet_send_dest(server, server->router->connection,
+                                  SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                                  channel_ids[i], SILC_ID_CHANNEL,
+                                  channel_users_modes[i]->data, 
+                                  channel_users_modes[i]->len,
+                                  FALSE);
+      silc_buffer_free(channel_users_modes[i]);
+    }
+    silc_free(channel_users_modes);
+    silc_free(channel_ids);
   }
 }
 
@@ -3436,8 +3459,7 @@ SILC_TASK_CALLBACK(silc_server_failure_callback)
 
   if (f->sock->protocol) {
     f->sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
-    f->sock->protocol->execute(f->server->timeout_queue, 0,
-                              f->sock->protocol, f->sock->sock, 0, 0);
+    silc_protocol_execute(f->sock->protocol, f->server->timeout_queue, 0, 0);
   }
 
   silc_free(f);
@@ -3767,8 +3789,7 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
   sock->protocol = protocol;
       
   /* Run the protocol */
-  protocol->execute(server->timeout_queue, 0, protocol, 
-                   sock->sock, 0, 0);
+  silc_protocol_execute(protocol, server->timeout_queue, 0, 0);
 
   /* Re-register re-key timeout */
   silc_task_register(server->timeout_queue, sock->sock, 
@@ -3793,7 +3814,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
-    silc_protocol_cancel(server->timeout_queue, protocol);
+    silc_protocol_cancel(protocol, server->timeout_queue);
     silc_protocol_free(protocol);
     sock->protocol = NULL;
     if (ctx->packet)