updates.
[silc.git] / apps / silcd / server.c
index 786566f0301812b55a6422c1fd7cb0078f31c740..7b1d27f7cf31663bd18c5d3a25ac291cb223eb84 100644 (file)
@@ -120,6 +120,14 @@ int silc_server_init(SilcServer server)
   assert(server);
   assert(server->config);
 
+  /* Set public and private keys */
+  server->public_key = server->config->server_keys->public_key;
+  server->private_key = server->config->server_keys->private_key;
+  if (!server->public_key || !server->private_key) {
+    SILC_LOG_ERROR(("Server public key and/or private key does not exist"));
+    return FALSE;
+  }
+
   /* 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 +160,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. */
@@ -744,6 +700,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;
@@ -848,8 +805,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SilcServerEntry id_entry;
   SilcBuffer packet;
   SilcServerHBContext hb_context;
-  SilcServerRekeyContext rekey;
   unsigned char *id_string;
+  SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -914,7 +871,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   sock->type = SILC_SOCKET_TYPE_ROUTER;
   server->id_entry->router = id_entry;
   server->router = id_entry;
-  server->router->data.registered = TRUE;
+  idata = (SilcIDListData)sock->user_data;
+  idata->registered = TRUE;
 
   /* Perform keepalive. The `hb_context' will be freed automatically
      when finally calling the silc_socket_free function. XXX hardcoded 
@@ -926,14 +884,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
                            server->timeout_queue);
 
   /* Register re-key timeout */
-  /* XXX this leaks memory as this is not freed anywhere, currently */
-  rekey = silc_calloc(1, sizeof(*rekey));
-  rekey->server = server;
-  rekey->sock = sock;
-  rekey->timeout = 3600; /* 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,
-                    (void *)rekey, rekey->timeout, 0,
+                    (void *)sock, idata->rekey->timeout, 0,
                     SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 
   /* If we are router then announce our possible servers. */
@@ -1099,6 +1054,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;
@@ -1756,25 +1712,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) {
-
-      SilcServerKEInternalContext *proto_ctx = 
-       (SilcServerKEInternalContext *)sock->protocol->context;
+       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
 
-      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."));
@@ -1787,25 +1758,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) {
-
-      SilcServerKEInternalContext *proto_ctx = 
-       (SilcServerKEInternalContext *)sock->protocol->context;
+       (sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE ||
+        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)) {
 
-      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."));
@@ -3440,7 +3426,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. */
@@ -3482,12 +3468,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;
   }
 
@@ -3495,7 +3483,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;
   }
 
@@ -3510,7 +3499,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;
     }
   }
@@ -3606,8 +3596,9 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server,
 
 SILC_TASK_CALLBACK(silc_server_rekey_callback)
 {
-  SilcServerRekeyContext rekey = (SilcServerRekeyContext)context;
-  SilcServer server = rekey->server;
+  SilcSocketConnection sock = (SilcSocketConnection)context;
+  SilcIDListData idata = (SilcIDListData)sock->user_data;
+  SilcServer server = (SilcServer)idata->rekey->context;
   SilcProtocol protocol;
   SilcServerRekeyInternalContext *proto_ctx;
 
@@ -3617,24 +3608,24 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
      to the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->server = (void *)server;
-  proto_ctx->context = context;
-  proto_ctx->sock = rekey->sock;
+  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. */
   silc_protocol_alloc(SILC_PROTOCOL_SERVER_REKEY, 
                      &protocol, proto_ctx, silc_server_rekey_final);
-  rekey->sock->protocol = protocol;
+  sock->protocol = protocol;
       
   /* Run the protocol */
   protocol->execute(server->timeout_queue, 0, protocol, 
-                   rekey->sock->sock, 0, 0);
+                   sock->sock, 0, 0);
 
   /* Re-register re-key timeout */
-  silc_task_register(server->timeout_queue, 0
+  silc_task_register(server->timeout_queue, sock->sock
                     silc_server_rekey_callback,
-                    context, rekey->timeout, 0,
+                    context, idata->rekey->timeout, 0,
                     SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
@@ -3654,10 +3645,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)
@@ -3667,18 +3657,14 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
   }
 
   /* 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);
-  }
 
   /* 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)