Added SILC Thread Queue API
[runtime.git] / apps / silc / clientconfig.c
index af12288ffb6d0b03629800fdf0d3bf9aeeaaa9cb..2fc31faf06b09d4f5833e2537f3af38a5ca3e766 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2001 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   GNU General Public License for more details.
 
 */
-/*
- * $Id$
- * $Log$
- * Revision 1.3  2000/07/05 06:12:05  priikone
- *     Global cosmetic changes.
- *
- * Revision 1.2  2000/07/03 05:49:11  priikone
- *     Remove ':' from the end of line when in commands section.  Command
- *     execution should work now from config file ok.
- *
- * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
- *     Imported from internal CVS/Added Log headers.
- *
- *
- */
+/* $Id$ */
 
 #include "clientincludes.h"
 #include "clientconfig.h"
@@ -43,9 +29,11 @@ SilcClientConfigSection silc_client_config_sections[] = {
   { "[cipher]", 
     SILC_CLIENT_CONFIG_SECTION_TYPE_CIPHER, 4 },
   { "[pkcs]", 
-    SILC_CLIENT_CONFIG_SECTION_TYPE_PKCS, 2 },
+    SILC_CLIENT_CONFIG_SECTION_TYPE_PKCS, 1 },
   { "[hash]", 
     SILC_CLIENT_CONFIG_SECTION_TYPE_HASH_FUNCTION, 4 },
+  { "[hmac]", 
+    SILC_CLIENT_CONFIG_SECTION_TYPE_HMAC, 3 },
   { "[connection]", 
     SILC_CLIENT_CONFIG_SECTION_TYPE_CONNECTION, 4 },
   { "[commands]", 
@@ -109,7 +97,7 @@ int silc_client_config_parse(SilcClientConfig config, SilcBuffer buffer,
                             SilcClientConfigParse *return_config)
 {
   int i, begin;
-  unsigned int linenum;
+  int linenum;
   char line[1024], *cp;
   SilcClientConfigSection *cptr = NULL;
   SilcClientConfigParse parse = *return_config, first = NULL;
@@ -286,28 +274,28 @@ int silc_client_config_parse_lines(SilcClientConfig config,
       if (ret < 0)
        break;
 
-      /* Get block length */
+      /* Get key length */
       ret = silc_config_get_token(line, &tmp);
       if (ret < 0)
        break;
       if (ret == 0) {
-       fprintf(stderr, "%s:%d: Cipher block length not defined\n",
+       fprintf(stderr, "%s:%d: Cipher key length not defined\n",
                config->filename, pc->linenum);
        break;
       }
-      config->cipher->block_len = atoi(tmp);
+      config->cipher->key_len = atoi(tmp);
       silc_free(tmp);
 
-      /* Get key length */
+      /* Get block length */
       ret = silc_config_get_token(line, &tmp);
       if (ret < 0)
        break;
       if (ret == 0) {
-       fprintf(stderr, "%s:%d: Cipher key length not defined\n",
+       fprintf(stderr, "%s:%d: Cipher block length not defined\n",
                config->filename, pc->linenum);
        break;
       }
-      config->cipher->key_len = atoi(tmp);
+      config->cipher->block_len = atoi(tmp);
       silc_free(tmp);
 
       check = TRUE;
@@ -339,18 +327,6 @@ int silc_client_config_parse_lines(SilcClientConfig config,
        break;
       }
 
-      /* Get key length */
-      ret = silc_config_get_token(line, &tmp);
-      if (ret < 0)
-       break;
-      if (ret == 0) {
-       fprintf(stderr, "%s:%d: PKCS key length not defined\n",
-               config->filename, pc->linenum);
-       break;
-      }
-      config->pkcs->key_len = atoi(tmp);
-      silc_free(tmp);
-
       check = TRUE;
       break;
 
@@ -413,6 +389,57 @@ int silc_client_config_parse_lines(SilcClientConfig config,
       check = TRUE;
       break;
 
+    case SILC_CLIENT_CONFIG_SECTION_TYPE_HMAC:
+
+      if (!config->hmac) {
+       config->hmac = silc_calloc(1, sizeof(*config->hmac));
+       config->hmac->next = NULL;
+       config->hmac->prev = NULL;
+      } else {
+       if (!config->hmac->next) {
+         config->hmac->next = 
+           silc_calloc(1, sizeof(*config->hmac->next));
+         config->hmac->next->next = NULL;
+         config->hmac->next->prev = config->hmac;
+         config->hmac = config->hmac->next;
+       }
+      }
+
+      /* Get HMAC name */
+      ret = silc_config_get_token(line, &config->hmac->alg_name);
+      if (ret < 0)
+       break;
+      if (ret == 0) {
+       fprintf(stderr, "%s:%d: HMAC name not defined\n",
+               config->filename, pc->linenum);
+       break;
+      }
+      
+      /* Get Hash function name */
+      ret = silc_config_get_token(line, &config->hmac->sim_name);
+      if (ret < 0)
+       break;
+      if (ret == 0) {
+       fprintf(stderr, "%s:%d: Hash function name not defined\n",
+               config->filename, pc->linenum);
+       break;
+      }
+
+      /* Get MAC length */
+      ret = silc_config_get_token(line, &tmp);
+      if (ret < 0)
+       break;
+      if (ret == 0) {
+       fprintf(stderr, "%s:%d: HMAC's MAC length not defined\n",
+               config->filename, pc->linenum);
+       break;
+      }
+      config->hmac->key_len = atoi(tmp);
+      silc_free(tmp);
+
+      check = TRUE;
+      break;
+
     case SILC_CLIENT_CONFIG_SECTION_TYPE_CONNECTION:
 
       if (!config->conns) {
@@ -449,10 +476,10 @@ int silc_client_config_parse_lines(SilcClientConfig config,
        }
 
        if (!strcmp(tmp, SILC_CLIENT_CONFIG_AUTH_METH_PASSWD))
-         config->conns->auth_meth = SILC_PROTOCOL_CONN_AUTH_PASSWORD;
+         config->conns->auth_meth = SILC_AUTH_PASSWORD;
 
        if (!strcmp(tmp, SILC_CLIENT_CONFIG_AUTH_METH_PUBKEY))
-         config->conns->auth_meth = SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY;
+         config->conns->auth_meth = SILC_AUTH_PUBLIC_KEY;
 
        silc_free(tmp);
       }
@@ -527,6 +554,8 @@ int silc_client_config_parse_lines(SilcClientConfig config,
     config->pkcs = config->pkcs->prev;
   while (config->hash_func && config->hash_func->prev)
     config->hash_func = config->hash_func->prev;
+  while (config->hmac && config->hmac->prev)
+    config->hmac = config->hmac->prev;
   while (config->conns && config->conns->prev)
     config->conns = config->conns->prev;
   while (config->commands && config->commands->prev)
@@ -540,33 +569,43 @@ int silc_client_config_parse_lines(SilcClientConfig config,
 /* Registers configured ciphers. These can then be allocated by the
    client when needed. */
 
-void silc_client_config_register_ciphers(SilcClientConfig config)
+bool silc_client_config_register_ciphers(SilcClientConfig config)
 {
   SilcClientConfigSectionAlg *alg;
-  SilcClient client = (SilcClient)config->client;
+  SilcClientInternal app = (SilcClientInternal)config->client;
+  SilcClient client = app->client;
 
   SILC_LOG_DEBUG(("Registering configured ciphers"));
 
+  if (!config->cipher)
+    return FALSE;
+
   alg = config->cipher;
   while(alg) {
 
     if (!alg->sim_name) {
-      /* Crypto module is supposed to be built in. Nothing to be done
-        here except to test that the cipher really is built in. */
-      SilcCipher tmp = NULL;
+      /* Crypto module is supposed to be built in. Get the pointer to the
+        built in cipher and register it. */
+      int i;
 
-      if (silc_cipher_alloc(alg->alg_name, &tmp) == FALSE) {
-       SILC_LOG_ERROR(("Unsupported cipher `%s'", alg->alg_name));
+      for (i = 0; silc_default_ciphers[i].name; i++)
+       if (!strcmp(silc_default_ciphers[i].name, alg->alg_name)) {
+         silc_cipher_register(&silc_default_ciphers[i]);
+         break;
+       }
+
+      if (!silc_cipher_is_supported(alg->alg_name)) {
+       SILC_LOG_ERROR(("Unknown cipher `%s'", alg->alg_name));
        silc_client_stop(client);
        exit(1);
       }
-      silc_cipher_free(tmp);
 
 #ifdef SILC_SIM
     } else {
       /* Load (try at least) the crypto SIM module */
       SilcCipherObject cipher;
       SilcSimContext *sim;
+      char *alg_name;
 
       memset(&cipher, 0, sizeof(cipher));
       cipher.name = alg->alg_name;
@@ -577,34 +616,40 @@ void silc_client_config_register_ciphers(SilcClientConfig config)
       sim->type = SILC_SIM_CIPHER;
       sim->libname = alg->sim_name;
 
+      alg_name = strdup(alg->alg_name);
+      if (strchr(alg_name, '-'))
+       *strchr(alg_name, '-') = '\0';
+
       if ((silc_sim_load(sim))) {
        cipher.set_key = 
-         silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
+         silc_sim_getsym(sim, silc_sim_symname(alg_name, 
                                                SILC_CIPHER_SIM_SET_KEY));
        SILC_LOG_DEBUG(("set_key=%p", cipher.set_key));
        cipher.set_key_with_string = 
-         silc_sim_getsym(sim, silc_sim_symname(alg->alg_name, 
-                                               SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
+         silc_sim_getsym(sim, silc_sim_symname(alg_name, 
+                                        SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
        SILC_LOG_DEBUG(("set_key_with_string=%p", cipher.set_key_with_string));
        cipher.encrypt = 
-         silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+         silc_sim_getsym(sim, silc_sim_symname(alg_name,
                                                SILC_CIPHER_SIM_ENCRYPT_CBC));
        SILC_LOG_DEBUG(("encrypt_cbc=%p", cipher.encrypt));
         cipher.decrypt = 
-         silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+         silc_sim_getsym(sim, silc_sim_symname(alg_name,
                                                SILC_CIPHER_SIM_DECRYPT_CBC));
        SILC_LOG_DEBUG(("decrypt_cbc=%p", cipher.decrypt));
         cipher.context_len = 
-         silc_sim_getsym(sim, silc_sim_symname(alg->alg_name,
+         silc_sim_getsym(sim, silc_sim_symname(alg_name,
                                                SILC_CIPHER_SIM_CONTEXT_LEN));
        SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
 
        /* Put the SIM to the table of all SIM's in client */
-       client->sim = silc_realloc(client->sim,
-                                  sizeof(*client->sim) * 
-                                  (client->sim_count + 1));
-       client->sim[client->sim_count] = sim;
-       client->sim_count++;
+       app->sim = silc_realloc(app->sim,
+                                  sizeof(*app->sim) * 
+                                  (app->sim_count + 1));
+       app->sim[app->sim_count] = sim;
+       app->sim_count++;
+
+       silc_free(alg_name);
       } else {
        SILC_LOG_ERROR(("Error configuring ciphers"));
        silc_client_stop(client);
@@ -618,60 +663,74 @@ void silc_client_config_register_ciphers(SilcClientConfig config)
 
     alg = alg->next;
   }
+
+  return TRUE;
 }
 
 /* Registers configured PKCS's. */
-/* XXX: This really doesn't do anything now since we have statically
-   registered our PKCS's. This should be implemented when PKCS works
-   as SIM's. This checks now only that the PKCS user requested is 
-   really out there. */
 
-void silc_client_config_register_pkcs(SilcClientConfig config)
+bool silc_client_config_register_pkcs(SilcClientConfig config)
 {
   SilcClientConfigSectionAlg *alg = config->pkcs;
-  SilcClient client = (SilcClient)config->client;
-  SilcPKCS tmp = NULL;
+  SilcClientInternal app = (SilcClientInternal)config->client;
+  SilcClient client = app->client;
 
   SILC_LOG_DEBUG(("Registering configured PKCS"));
 
-  while(alg) {
+  if (!alg)
+    return FALSE;
 
-    if (silc_pkcs_alloc(alg->alg_name, &tmp) == FALSE) {
-      SILC_LOG_ERROR(("Unsupported PKCS `%s'", alg->alg_name));
+  while(alg) {
+    int i;
+    
+    for (i = 0; silc_default_pkcs[i].name; i++)
+      if (!strcmp(silc_default_pkcs[i].name, alg->alg_name)) {
+       silc_pkcs_register(&silc_default_pkcs[i]);
+       break;
+      }
+    
+    if (!silc_pkcs_is_supported(alg->alg_name)) {
+      SILC_LOG_ERROR(("Unknown PKCS `%s'", alg->alg_name));
       silc_client_stop(client);
       exit(1);
     }
-    silc_free(tmp);
 
     alg = alg->next;
   }
+
+  return TRUE;
 }
 
-/* Registers configured hash functions. These can then be allocated by the
+/* Registers configured hash funtions. These can then be allocated by the
    client when needed. */
 
-void silc_client_config_register_hashfuncs(SilcClientConfig config)
+bool silc_client_config_register_hashfuncs(SilcClientConfig config)
 {
   SilcClientConfigSectionAlg *alg;
-  SilcClient client = (SilcClient)config->client;
+  SilcClientInternal app = (SilcClientInternal)config->client;
+  SilcClient client = app->client;
 
   SILC_LOG_DEBUG(("Registering configured hash functions"));
 
+  if (!config->hash_func)
+    return FALSE;
+
   alg = config->hash_func;
   while(alg) {
-
     if (!alg->sim_name) {
-      /* Hash module is supposed to be built in. Nothing to be done
-        here except to test that the hash function really is built in. */
-      SilcHash tmp = NULL;
-
-      if (silc_hash_alloc(alg->alg_name, &tmp) == FALSE) {
-       SILC_LOG_ERROR(("Unsupported hash function `%s'", alg->alg_name));
+      int i;
+      
+      for (i = 0; silc_default_hash[i].name; i++)
+       if (!strcmp(silc_default_hash[i].name, alg->alg_name)) {
+         silc_hash_register(&silc_default_hash[i]);
+         break;
+       }
+      
+      if (!silc_hash_is_supported(alg->alg_name)) {
+       SILC_LOG_ERROR(("Unknown hash function `%s'", alg->alg_name));
        silc_client_stop(client);
        exit(1);
       }
-      silc_free(tmp);
-
 #ifdef SILC_SIM
     } else {
       /* Load (try at least) the hash SIM module */
@@ -706,26 +765,63 @@ void silc_client_config_register_hashfuncs(SilcClientConfig config)
        SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
 
        /* Put the SIM to the table of all SIM's in client */
-       client->sim = silc_realloc(client->sim,
-                                  sizeof(*client->sim) * 
-                                  (client->sim_count + 1));
-       client->sim[client->sim_count] = sim;
-       client->sim_count++;
+       app->sim = silc_realloc(app->sim,
+                                  sizeof(*app->sim) * 
+                                  (app->sim_count + 1));
+       app->sim[app->sim_count] = sim;
+       app->sim_count++;
       } else {
        SILC_LOG_ERROR(("Error configuring hash functions"));
        silc_client_stop(client);
        exit(1);
       }
 
-      /* Register the cipher */
+      /* Register the hash function */
       silc_hash_register(&hash);
 #endif
     }
-
     alg = alg->next;
   }
+
+  return TRUE;
 }
 
+/* Registers configured HMACs. These can then be allocated by the
+   client when needed. */
+
+bool silc_client_config_register_hmacs(SilcClientConfig config)
+{
+  SilcClientConfigSectionAlg *alg;
+  SilcClientInternal app = (SilcClientInternal)config->client;
+  SilcClient client = app->client;
+
+  SILC_LOG_DEBUG(("Registering configured HMACs"));
+
+  if (!config->hmac)
+    return FALSE;
+
+  alg = config->hmac;
+  while(alg) {
+    SilcHmacObject hmac;
+    
+    if (!silc_hash_is_supported(alg->sim_name)) {
+      SILC_LOG_ERROR(("Unknown hash function `%s' for HMAC `%s'", 
+                     alg->sim_name, alg->alg_name));
+      silc_client_stop(client);
+      exit(1);
+    }
+    
+    /* Register the HMAC */
+    memset(&hmac, 0, sizeof(hmac));
+    hmac.name = alg->alg_name;
+    hmac.len = alg->key_len;
+    silc_hmac_register(&hmac);
+
+    alg = alg->next;
+  }
+
+  return TRUE;
+}
 
 SilcClientConfigSectionConnection *
 silc_client_config_find_connection(SilcClientConfig config,