updates.
[silc.git] / apps / silcd / server.c
index 1ba577a403e9e11106c0b27bcac287a30e74f475..639c3bbb732a8eb75d3b55028ba544717ac42e77 100644 (file)
@@ -120,6 +120,16 @@ int silc_server_init(SilcServer server)
   assert(server);
   assert(server->config);
 
+  /* Set public and private keys */
+  if (!server->config->server_keys ||
+      !server->config->server_keys->public_key || 
+      !server->config->server_keys->private_key) {
+    SILC_LOG_ERROR(("Server public key and/or private key does not exist"));
+    return FALSE;
+  }
+  server->public_key = server->config->server_keys->public_key;
+  server->private_key = server->config->server_keys->private_key;
+
   /* XXX After server is made as Silc Server Library this can be given
      as argument, for now this is hard coded */
   server->params = silc_calloc(1, sizeof(*server->params));
@@ -152,58 +162,6 @@ int silc_server_init(SilcServer server)
   /* Initialize none cipher */
   silc_cipher_alloc("none", &server->none_cipher);
 
-  /* XXXXX Generate RSA key pair */
-  {
-    unsigned char *public_key;
-    unsigned char *private_key;
-    uint32 pk_len, prv_len;
-    struct stat st;
-
-    if (stat("pubkey.pub", &st) < 0 && stat("privkey.prv", &st) < 0) {
-
-      if (silc_pkcs_alloc("rsa", &server->pkcs) == FALSE) {
-       SILC_LOG_ERROR(("Could not create RSA key pair"));
-       goto err0;
-      }
-      
-      if (server->pkcs->pkcs->init(server->pkcs->context, 
-                                  1024, server->rng) == FALSE) {
-       SILC_LOG_ERROR(("Could not generate RSA key pair"));
-       goto err0;
-      }
-      
-      public_key = server->pkcs->pkcs->get_public_key(server->pkcs->context,
-                                                     &pk_len);
-      private_key = server->pkcs->pkcs->get_private_key(server->pkcs->context,
-                                                       &prv_len);
-      
-      SILC_LOG_HEXDUMP(("public key"), public_key, pk_len);
-      SILC_LOG_HEXDUMP(("private key"), private_key, prv_len);
-      
-      server->public_key = 
-       silc_pkcs_public_key_alloc("rsa", "UN=root, HN=dummy",
-                                  public_key, pk_len);
-      server->private_key = 
-       silc_pkcs_private_key_alloc("rsa", private_key, prv_len);
-      
-      /* XXX Save keys */
-      silc_pkcs_save_public_key("pubkey.pub", server->public_key,
-                               SILC_PKCS_FILE_PEM);
-      silc_pkcs_save_private_key("privkey.prv", server->private_key, NULL,
-                                SILC_PKCS_FILE_BIN);
-
-      memset(public_key, 0, pk_len);
-      memset(private_key, 0, prv_len);
-      silc_free(public_key);
-      silc_free(private_key);
-    } else {
-      silc_pkcs_load_public_key("pubkey.pub", &server->public_key,
-                               SILC_PKCS_FILE_PEM);
-      silc_pkcs_load_private_key("privkey.prv", &server->private_key,
-                                SILC_PKCS_FILE_BIN);
-    }
-  }
-
   /* Create a listening server. Note that our server can listen on
      multiple ports. All listeners are created here and now. */
   /* XXX Still check this whether to use server_info or listen_port. */
@@ -558,6 +516,9 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
   SilcServerKEInternalContext *proto_ctx;
   int sock;
 
+  SILC_LOG_INFO(("Connecting to the router %s on port %d", 
+                sconn->remote_host, sconn->remote_port));
+
   /* Connect to remote host */
   sock = silc_net_create_connection(sconn->remote_port, 
                                    sconn->remote_host);
@@ -744,6 +705,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
                                        ctx->ske->prop->pkcs,
                                        ctx->ske->prop->hash,
                                        ctx->ske->prop->hmac,
+                                       ctx->ske->prop->group,
                                        ctx->responder)) {
     silc_protocol_free(protocol);
     sock->protocol = NULL;
@@ -898,7 +860,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
 
   /* Add the connected router to local server list */
   server->standalone = FALSE;
-  id_entry = silc_idlist_add_server(server->local_list, sock->hostname,
+  id_entry = silc_idlist_add_server(server->local_list, strdup(sock->hostname),
                                    SILC_ROUTER, ctx->dest_id, NULL, sock);
   if (!id_entry) {
     if (ctx->dest_id)
@@ -927,7 +889,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
                            server->timeout_queue);
 
   /* Register re-key timeout */
-  idata->rekey->timeout = 60; /* XXX hardcoded */
+  idata->rekey->timeout = 3600; /* XXX hardcoded */
   idata->rekey->context = (void *)server;
   silc_task_register(server->timeout_queue, sock->sock, 
                     silc_server_rekey_callback,
@@ -1000,15 +962,19 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
      process. Either we have to do our own resolver stuff or in the future
      we can use threads. */
   /* Perform name and address lookups for the remote host. */
-  silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
-  if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
-      !newsocket->ip) {
-    SILC_LOG_ERROR(("IP/DNS lookup failed"));
-    server->stat.conn_failures++;
-    return;
+  if (!silc_net_check_host_by_sock(sock, &newsocket->hostname, 
+                                  &newsocket->ip)) {
+    if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
+       !newsocket->ip) {
+      SILC_LOG_ERROR(("IP/DNS lookup failed %s",
+                     newsocket->hostname ? newsocket->hostname :
+                     newsocket->ip ? newsocket->ip : ""));
+      server->stat.conn_failures++;
+      return;
+    }
+    if (!newsocket->hostname)
+      newsocket->hostname = strdup(newsocket->ip);
   }
-  if (!newsocket->hostname)
-    newsocket->hostname = strdup(newsocket->ip);
   newsocket->port = silc_net_get_remote_port(sock);
 
   SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
@@ -1097,6 +1063,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
                                        ctx->ske->prop->pkcs,
                                        ctx->ske->prop->hash,
                                        ctx->ske->prop->hmac,
+                                       ctx->ske->prop->group,
                                        ctx->responder)) {
     silc_protocol_free(protocol);
     sock->protocol = NULL;
@@ -1338,7 +1305,8 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     if (sock->outbuf->data - sock->outbuf->head)
      silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
 
-    ret = silc_server_packet_send_real(server, sock, TRUE);
+    /* Send the packet */
+    ret = silc_packet_send(sock, TRUE);
 
     /* If returned -2 could not write to connection now, will do
        it later. */
@@ -1412,7 +1380,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   if (idata) {
     idata->last_receive = time(NULL);
     cipher = idata->receive_key;
-    hmac = idata->hmac;
+    hmac = idata->hmac_receive;
   }
  
   /* Process the packet. This will call the parser that will then
@@ -1454,7 +1422,7 @@ static int silc_server_packet_decrypt_check(SilcPacketType packet_type,
 
   return FALSE;
 }
-
+  
 /* Parses whole packet, received earlier. */
 
 SILC_TASK_CALLBACK(silc_server_packet_parse_real)
@@ -1463,12 +1431,14 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   SilcServer server = (SilcServer)parse_ctx->context;
   SilcSocketConnection sock = parse_ctx->sock;
   SilcPacketContext *packet = parse_ctx->packet;
+  SilcIDListData idata = (SilcIDListData)sock->user_data;
   int ret;
 
   SILC_LOG_DEBUG(("Start"));
 
   /* Decrypt the received packet */
-  ret = silc_packet_decrypt(parse_ctx->cipher, parse_ctx->hmac, 
+  ret = silc_packet_decrypt(idata ? idata->receive_key : NULL, 
+                           idata ? idata->hmac_receive : NULL, 
                            packet->buffer, packet,
                            silc_server_packet_decrypt_check, parse_ctx);
   if (ret < 0)
@@ -1546,7 +1516,6 @@ void silc_server_packet_parse(SilcPacketParserContext *parser_context)
   SilcSocketConnection sock = parser_context->sock;
 
   switch (sock->type) {
-  case SILC_SOCKET_TYPE_CLIENT:
   case SILC_SOCKET_TYPE_UNKNOWN:
     /* Parse the packet with timeout */
     silc_task_register(server->timeout_queue, sock->sock,
@@ -1555,6 +1524,15 @@ void silc_server_packet_parse(SilcPacketParserContext *parser_context)
                       SILC_TASK_TIMEOUT,
                       SILC_TASK_PRI_NORMAL);
     break;
+  case SILC_SOCKET_TYPE_CLIENT:
+    /* Parse the packet with timeout (unless protocol is active) */
+    silc_task_register(server->timeout_queue, sock->sock,
+                      silc_server_packet_parse_real,
+                      (void *)parser_context, 0, 
+                      (sock->protocol ? 1 : 100000),
+                      SILC_TASK_TIMEOUT,
+                      SILC_TASK_PRI_NORMAL);
+    break;
   case SILC_SOCKET_TYPE_SERVER:
   case SILC_SOCKET_TYPE_ROUTER:
     /* Packets from servers are parsed as soon as possible */
@@ -1754,25 +1732,40 @@ void silc_server_packet_parse_type(SilcServer server,
       break;
 
     if (sock->protocol && sock->protocol->protocol &&
-       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
+       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
 
-      SilcServerKEInternalContext *proto_ctx = 
-       (SilcServerKEInternalContext *)sock->protocol->context;
-
-      if (proto_ctx->packet)
-       silc_packet_context_free(proto_ctx->packet);
+      if (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
+       SilcServerRekeyInternalContext *proto_ctx = 
+         (SilcServerRekeyInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
 
-      proto_ctx->packet = silc_packet_context_dup(packet);
-      proto_ctx->dest_id_type = packet->src_id_type;
-      proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                                         packet->src_id_type);
-      if (!proto_ctx->dest_id)
-       break;
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock, 0, 0);
+      } else {
+       SilcServerKEInternalContext *proto_ctx = 
+         (SilcServerKEInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+       proto_ctx->dest_id_type = packet->src_id_type;
+       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+                                           packet->src_id_type);
+       if (!proto_ctx->dest_id)
+         break;
 
-      /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock,
-                             0, 100000);
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock,
+                               0, 100000);
+      }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -1785,25 +1778,40 @@ void silc_server_packet_parse_type(SilcServer server,
       break;
 
     if (sock->protocol && sock->protocol->protocol &&
-       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
+       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
 
-      SilcServerKEInternalContext *proto_ctx = 
-       (SilcServerKEInternalContext *)sock->protocol->context;
-
-      if (proto_ctx->packet)
-       silc_packet_context_free(proto_ctx->packet);
+      if (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY) {
+       SilcServerRekeyInternalContext *proto_ctx = 
+         (SilcServerRekeyInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
 
-      proto_ctx->packet = silc_packet_context_dup(packet);
-      proto_ctx->dest_id_type = packet->src_id_type;
-      proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
-                                         packet->src_id_type);
-      if (!proto_ctx->dest_id)
-       break;
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock, 0, 0);
+      } else {
+       SilcServerKEInternalContext *proto_ctx = 
+         (SilcServerKEInternalContext *)sock->protocol->context;
+       
+       if (proto_ctx->packet)
+         silc_packet_context_free(proto_ctx->packet);
+       
+       proto_ctx->packet = silc_packet_context_dup(packet);
+       proto_ctx->dest_id_type = packet->src_id_type;
+       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
+                                           packet->src_id_type);
+       if (!proto_ctx->dest_id)
+         break;
 
-      /* Let the protocol handle the packet */
-      sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock,
-                             0, 100000);
+       /* Let the protocol handle the packet */
+       sock->protocol->execute(server->timeout_queue, 0, 
+                               sock->protocol, sock->sock,
+                               0, 100000);
+      }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
                      "protocol active, packet dropped."));
@@ -1951,8 +1959,7 @@ void silc_server_packet_parse_type(SilcServer server,
 
       /* Let the protocol handle the packet */
       sock->protocol->execute(server->timeout_queue, 0, 
-                             sock->protocol, sock->sock,
-                             0, 100000);
+                             sock->protocol, sock->sock, 0, 0);
     } else {
       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
                      "protocol active, packet dropped."));
@@ -1995,7 +2002,12 @@ SILC_TASK_CALLBACK(silc_server_close_connection_final)
 void silc_server_close_connection(SilcServer server,
                                  SilcSocketConnection sock)
 {
-  SILC_LOG_DEBUG(("Closing connection %d", sock->sock));
+  SILC_LOG_INFO(("Closing connection %s:%d [%s] (%d)", sock->hostname,
+                sock->port,  
+                (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+                 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+                 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+                 "Router"), sock->sock));
 
   /* We won't listen for this connection anymore */
   silc_schedule_unset_listen_fd(sock->sock);
@@ -2084,7 +2096,7 @@ void silc_server_free_client_data(SilcServer server,
     if (sock->outbuf->data - sock->outbuf->head)
      silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
 
-    silc_server_packet_send_real(server, sock, TRUE);
+    silc_packet_send(sock, TRUE);
 
     SILC_SET_CONNECTION_FOR_INPUT(sock->sock);
     SILC_UNSET_OUTBUF_PENDING(sock);
@@ -3438,7 +3450,7 @@ void silc_server_save_users_on_channel(SilcServer server,
   }
 }
 
-/* Lookups route to the client indicated by `id' client ID. The connection
+/* Lookups route to the client indicated by the `id_data'. The connection
    object and internal data object is returned. Returns NULL if route
    could not be found to the client. If the `client_id' is specified then
    it is used and the `id_data' is ignored. */
@@ -3480,12 +3492,14 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server,
       /* We are of course in this case the client's router thus the real
         "router" of the client is the server who owns the client. Thus
         we will send the packet to that server. */
-      *idata = (SilcIDListData)client->router;
+      if (idata)
+       *idata = (SilcIDListData)client->router;
       return client->router->connection;
     }
 
     /* Seems that client really is directly connected to us */
-    *idata = (SilcIDListData)client;
+    if (idata)
+      *idata = (SilcIDListData)client;
     return client->connection;
   }
 
@@ -3493,7 +3507,8 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server,
      server our action is to send the packet to our router. */
   if (server->server_type == SILC_SERVER && !server->standalone) {
     silc_free(id);
-    *idata = (SilcIDListData)server->router;
+    if (idata)
+      *idata = (SilcIDListData)server->router;
     return server->router->connection;
   }
 
@@ -3508,7 +3523,8 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server,
       dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
 
       silc_free(id);
-      *idata = (SilcIDListData)dst_sock->user_data;
+      if (idata)
+       *idata = (SilcIDListData)dst_sock->user_data;
       return dst_sock;
     }
   }
@@ -3618,6 +3634,7 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
   proto_ctx->server = (void *)server;
   proto_ctx->sock = sock;
   proto_ctx->responder = FALSE;
+  proto_ctx->pfs = idata->rekey->pfs;
       
   /* Perform rekey protocol. Will call the final callback after the
      protocol is over. */
@@ -3652,10 +3669,9 @@ 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_free(protocol);
     sock->protocol = NULL;
-    if (ctx->keymat)
-      silc_ske_free_key_material(ctx->keymat);
     if (ctx->packet)
       silc_packet_context_free(ctx->packet);
     if (ctx->ske)
@@ -3664,19 +3680,17 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
     return;
   }
 
+#if 0
   /* Take the keys into use */
-  if (ctx->pfs == TRUE) {
-
-  } else {
-    /* Then just generate the new keys and take them into use */
+  if (ctx->pfs == TRUE)
+    silc_server_protocol_rekey_generate_pfs(server, ctx);
+  else
     silc_server_protocol_rekey_generate(server, ctx);
-  }
+#endif
 
   /* Cleanup */
   silc_protocol_free(protocol);
   sock->protocol = NULL;
-  if (ctx->keymat)
-    silc_ske_free_key_material(ctx->keymat);
   if (ctx->packet)
     silc_packet_context_free(ctx->packet);
   if (ctx->ske)