Added remote version control support to server.
[silc.git] / apps / silcd / server.c
index fab3d975a72344ea6c0c22dc404a0e3c88f060a1..4dc47c92ae196841f3ce80228cb22d57bc8e4688 100644 (file)
@@ -74,7 +74,7 @@ void silc_server_free(SilcServer server)
 {
   if (server) {
 #ifdef SILC_SIM
-    SilcSimContext *sim;
+    SilcSim sim;
 #endif
 
     silc_free(server->local_list);
@@ -765,20 +765,18 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     conn = sconn->conn;
 
   if (conn) {
-    /* Match found. Use the configured authentication method */
+    /* Match found. Use the configured authentication method. Take only
+       the passphrase, since for public key auth we automatically use
+       our local key pair. */
     if (conn->passphrase) {
-      if (conn->publickey && !server->config->prefer_passphrase_auth) {
-       proto_ctx->auth_data = conn->publickey;
-       proto_ctx->auth_data_len = 0;
+      if (conn->publickeys && !server->config->prefer_passphrase_auth) {
        proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
       } else {
        proto_ctx->auth_data = strdup(conn->passphrase);
        proto_ctx->auth_data_len = strlen(conn->passphrase);
        proto_ctx->auth_meth = SILC_AUTH_PASSWORD;
       }
-    } else if (conn->publickey) {
-      proto_ctx->auth_data = conn->publickey;
-      proto_ctx->auth_data_len = 0;
+    } else if (conn->publickeys) {
       proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
     } else {
       proto_ctx->auth_meth = SILC_AUTH_NONE;
@@ -845,7 +843,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SilcBuffer packet;
   SilcServerHBContext hb_context;
   unsigned char *id_string;
-  uint32 id_len;
+  SilcUInt32 id_len;
   SilcIDListData idata;
   SilcServerConfigConnParams *param;
 
@@ -914,6 +912,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
                                    SILC_ROUTER, ctx->dest_id, NULL, sock);
   if (!id_entry) {
     silc_free(ctx->dest_id);
+    SILC_LOG_ERROR(("Cannot add new server entry to cache"));
     silc_server_disconnect_remote(server, sock, "Server closed connection: "
                                  "Authentication failed");
     goto out;
@@ -1035,7 +1034,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
      later when outgoing data is available. */
   SILC_REGISTER_CONNECTION_FOR_IO(sock->sock);
 
-  SILC_LOG_INFO(("Incoming connection from %s (%s)", sock->hostname,
+  SILC_LOG_INFO(("Incoming connection %s (%s)", sock->hostname,
                 sock->ip));
 
   port = server->sockets[server->sock]->port; /* Listenning port */
@@ -1284,8 +1283,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   SilcServerHBContext hb_context;
   SilcUnknownEntry entry = (SilcUnknownEntry)sock->user_data;
   void *id_entry;
-  uint32 hearbeat_timeout = server->config->param.keepalive_secs;
-  uint32 num_sockets;
+  SilcUInt32 hearbeat_timeout = server->config->param.keepalive_secs;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -1310,39 +1308,22 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
 
   entry->data.last_receive = time(NULL);
 
-  num_sockets = silc_server_num_sockets_by_ip(server, sock->ip);
-
   switch (ctx->conn_type) {
   case SILC_SOCKET_TYPE_CLIENT:
     {
       SilcClientEntry client;
       SilcServerConfigClient *conn = ctx->cconfig;
-      uint32 max_per_host = server->config->param.connections_max_per_host;
-
-      /* Check for maximum connections limit */
-      if (conn->param) {
-       if (conn->param->connections_max &&
-           server->stat.my_clients >= conn->param->connections_max) {
-         silc_server_disconnect_remote(server, sock, 
-                                       "Server closed connection: "
-                                       "Server is full, try again later");
-         server->stat.auth_failures++;
-         goto out;
-       }
-
-       max_per_host = conn->param->connections_max_per_host;
-      }
 
-      if (num_sockets > max_per_host) {
-       silc_server_disconnect_remote(server, sock, 
-                                     "Server closed connection: "
-                                     "Too many connections from your host");
+      /* Verify whether this connection is after all allowed to connect */
+      if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
+                                         &server->config->param,
+                                         conn->param, ctx->ske)) {
        server->stat.auth_failures++;
        goto out;
       }
 
       SILC_LOG_DEBUG(("Remote host is client"));
-      SILC_LOG_INFO(("Connection from %s (%s) is client", sock->hostname,
+      SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname,
                     sock->ip));
 
       /* Add the client to the client ID cache. The nickname and Client ID
@@ -1383,68 +1364,58 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       bool backup_local = FALSE;
       bool backup_router = FALSE;
       char *backup_replace_ip = NULL;
-      uint16 backup_replace_port = 0;
+      SilcUInt16 backup_replace_port = 0;
       SilcServerConfigServer *sconn = ctx->sconfig;
       SilcServerConfigRouter *rconn = ctx->rconfig;
-      uint32 max_per_host = server->config->param.connections_max_per_host;
-
-      if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER && rconn) {
-       if (rconn->param) {
-         /* Check for maximum connections limit */
-         if (rconn->param->connections_max &&
-             server->stat.my_routers >= rconn->param->connections_max) {
-           silc_server_disconnect_remote(server, sock, 
-                                         "Server closed connection: "
-                                         "Server is full, try again later");
-           server->stat.auth_failures++;
-           goto out;
-         }
-         max_per_host = rconn->param->connections_max_per_host;
 
-         if (rconn->param->keepalive_secs)
-           hearbeat_timeout = rconn->param->keepalive_secs;
+      if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
+       /* Verify whether this connection is after all allowed to connect */
+       if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
+                                           &server->config->param,
+                                           rconn ? rconn->param : NULL, 
+                                           ctx->ske)) {
+         server->stat.auth_failures++;
+         goto out;
        }
 
-       initiator = rconn->initiator;
-       backup_local = rconn->backup_local;
-       backup_router = rconn->backup_router;
-       backup_replace_ip = rconn->backup_replace_ip;
-       backup_replace_port = rconn->backup_replace_port;
-      }
-
-      if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER && sconn) {
-       if (sconn->param) {
-         /* Check for maximum connections limit */
-         if (sconn->param->connections_max &&
-             server->stat.my_servers >= sconn->param->connections_max) {
-           silc_server_disconnect_remote(server, sock, 
-                                         "Server closed connection: "
-                                         "Server is full, try again later");
-           server->stat.auth_failures++;
-           goto out;
+       if (rconn) {
+         if (rconn->param) {
+           if (rconn->param->keepalive_secs)
+             hearbeat_timeout = rconn->param->keepalive_secs;
          }
-         max_per_host = sconn->param->connections_max_per_host;
 
-         if (sconn->param->keepalive_secs)
-           hearbeat_timeout = sconn->param->keepalive_secs;
+         initiator = rconn->initiator;
+         backup_local = rconn->backup_local;
+         backup_router = rconn->backup_router;
+         backup_replace_ip = rconn->backup_replace_ip;
+         backup_replace_port = rconn->backup_replace_port;
        }
-
-       backup_router = sconn->backup_router;
       }
 
-      if (num_sockets > max_per_host) {
-       silc_server_disconnect_remote(server, sock, 
-                                     "Server closed connection: "
-                                     "Too many connections from your host");
-       server->stat.auth_failures++;
-       goto out;
+      if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
+       /* Verify whether this connection is after all allowed to connect */
+       if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
+                                           &server->config->param,
+                                           sconn ? sconn->param : NULL, 
+                                           ctx->ske)) {
+         server->stat.auth_failures++;
+         goto out;
+       }
+       if (sconn) {
+         if (sconn->param) {
+           if (sconn->param->keepalive_secs)
+             hearbeat_timeout = sconn->param->keepalive_secs;
+         }
+
+         backup_router = sconn->backup_router;
+       }
       }
 
       SILC_LOG_DEBUG(("Remote host is %s", 
                      ctx->conn_type == SILC_SOCKET_TYPE_SERVER ? 
                      "server" : (backup_router ? 
                                  "backup router" : "router")));
-      SILC_LOG_INFO(("Connection from %s (%s) is %s", sock->hostname,
+      SILC_LOG_INFO(("Connection %s (%s) is %s", sock->hostname,
                     sock->ip, ctx->conn_type == SILC_SOCKET_TYPE_SERVER ? 
                     "server" : (backup_router ? 
                                 "backup router" : "router")));
@@ -1562,7 +1533,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
-  uint32 sequence = 0;
+  SilcUInt32 sequence = 0;
   int ret;
 
   if (!sock)
@@ -1664,7 +1635,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   /* If connection is disconnecting or disconnected we will ignore
      what we read. */
   if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
-    SILC_LOG_DEBUG(("Ignoring read data from disonnected connection"));
+    SILC_LOG_DEBUG(("Ignoring read data from disconnected connection"));
     return;
   }
 
@@ -1868,6 +1839,12 @@ void silc_server_packet_parse_type(SilcServer server,
     SILC_LOG_DEBUG(("Disconnect packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
+    if (silc_string_is_ascii(packet->buffer->data, packet->buffer->len)) {
+      /* Duplicate to null terminate the string. */
+      char *message = silc_memdup(packet->buffer->data, packet->buffer->len);
+      SILC_LOG_ERROR(("%s", message));
+      silc_free(message);
+    }
     break;
 
   case SILC_PACKET_SUCCESS:
@@ -2288,7 +2265,7 @@ void silc_server_packet_parse_type(SilcServer server,
 /* Creates connection to a remote router. */
 
 void silc_server_create_connection(SilcServer server,
-                                  const char *remote_host, uint32 port)
+                                  const char *remote_host, SilcUInt32 port)
 {
   SilcServerConnection sconn;
 
@@ -2844,6 +2821,9 @@ SILC_TASK_CALLBACK(silc_server_timeout_remote)
   if (!sock)
     return;
 
+  SILC_LOG_ERROR(("No response from %s (%s), Connection timeout",
+                 sock->hostname, sock->ip));
+
   /* 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) {
@@ -3026,11 +3006,11 @@ SILC_TASK_CALLBACK(silc_server_channel_key_rekey)
 
 bool silc_server_create_channel_key(SilcServer server, 
                                    SilcChannelEntry channel,
-                                   uint32 key_len)
+                                   SilcUInt32 key_len)
 {
   int i;
   unsigned char channel_key[32], hash[32];
-  uint32 len;
+  SilcUInt32 len;
 
   SILC_LOG_DEBUG(("Generating channel key"));
 
@@ -3109,7 +3089,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
   SilcChannelKeyPayload payload = NULL;
   SilcChannelID *id = NULL;
   unsigned char *tmp, hash[32];
-  uint32 tmp_len;
+  SilcUInt32 tmp_len;
   char *cipher;
 
   SILC_LOG_DEBUG(("Start"));
@@ -3281,7 +3261,7 @@ static void silc_server_announce_get_servers(SilcServer server,
 }
 
 static SilcBuffer 
-silc_server_announce_encode_notify(SilcNotifyType notify, uint32 argc, ...)
+silc_server_announce_encode_notify(SilcNotifyType notify, SilcUInt32 argc, ...)
 {
   va_list ap;
   SilcBuffer p;
@@ -3531,7 +3511,7 @@ void silc_server_announce_get_channels(SilcServer server,
                                       SilcBuffer *channels,
                                       SilcBuffer *channel_users,
                                       SilcBuffer **channel_users_modes,
-                                      uint32 *channel_users_modes_c,
+                                      SilcUInt32 *channel_users_modes_c,
                                       SilcBuffer **channel_topics,
                                       SilcChannelID ***channel_ids,
                                       unsigned long creation_time)
@@ -3540,8 +3520,8 @@ void silc_server_announce_get_channels(SilcServer server,
   SilcIDCacheEntry id_cache;
   SilcChannelEntry channel;
   unsigned char *cid;
-  uint32 id_len;
-  uint16 name_len;
+  SilcUInt32 id_len;
+  SilcUInt16 name_len;
   int len;
   int i = *channel_users_modes_c;
   bool announce;
@@ -3628,7 +3608,7 @@ void silc_server_announce_channels(SilcServer server,
   SilcBuffer channels = NULL, channel_users = NULL;
   SilcBuffer *channel_users_modes = NULL;
   SilcBuffer *channel_topics = NULL;
-  uint32 channel_users_modes_c = 0;
+  SilcUInt32 channel_users_modes_c = 0;
   SilcChannelID **channel_ids = NULL;
 
   SILC_LOG_DEBUG(("Announcing channels and channel users"));
@@ -3750,14 +3730,14 @@ void silc_server_get_users_on_channel(SilcServer server,
                                      SilcChannelEntry channel,
                                      SilcBuffer *user_list,
                                      SilcBuffer *mode_list,
-                                     uint32 *user_count)
+                                     SilcUInt32 *user_count)
 {
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
   SilcBuffer client_id_list;
   SilcBuffer client_mode_list;
   SilcBuffer idp;
-  uint32 list_count = 0, len = 0;
+  SilcUInt32 list_count = 0, len = 0;
 
   silc_hash_table_list(channel->user_list, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chl))
@@ -3803,11 +3783,11 @@ void silc_server_save_users_on_channel(SilcServer server,
                                       SilcClientID *noadd,
                                       SilcBuffer user_list,
                                       SilcBuffer mode_list,
-                                      uint32 user_count)
+                                      SilcUInt32 user_count)
 {
   int i;
-  uint16 idp_len;
-  uint32 mode;
+  SilcUInt16 idp_len;
+  SilcUInt32 mode;
   SilcClientID *client_id;
   SilcClientEntry client;
   SilcIDCacheEntry cache;
@@ -3894,7 +3874,7 @@ void silc_server_save_users_on_channel(SilcServer server,
 
 SilcSocketConnection silc_server_get_client_route(SilcServer server,
                                                  unsigned char *id_data,
-                                                 uint32 id_len,
+                                                 SilcUInt32 id_len,
                                                  SilcClientID *client_id,
                                                  SilcIDListData *idata)
 {
@@ -3979,8 +3959,8 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
   unsigned char *cid;
-  uint32 id_len;
-  uint16 name_len;
+  SilcUInt32 id_len;
+  SilcUInt16 name_len;
   int len;
 
   silc_hash_table_list(client->channels, &htl);