make sure error queue is totally emptied
[openssl.git] / crypto / conf / conf_mod.c
index cbbaf64f3cf54b4433deb63acced0bfff402288a..bae9fcaffaceae30dd4444269cb6c057298cd325 100644 (file)
@@ -57,6 +57,7 @@
  */
 
 #include <stdio.h>
+#include <ctype.h>
 #include <openssl/crypto.h>
 #include "cryptlib.h"
 #include <openssl/conf.h>
@@ -108,16 +109,20 @@ static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
 
 static void module_free(CONF_MODULE *md);
 static void module_finish(CONF_IMODULE *imod);
-static int module_run(CONF *cnf, char *name, char *value, unsigned long flags);
-static CONF_MODULE *module_add(DSO *dso, char *name,
+static int module_run(const CONF *cnf, char *name, char *value,
+                                         unsigned long flags);
+static CONF_MODULE *module_add(DSO *dso, const char *name,
                        conf_init_func *ifunc, conf_finish_func *ffunc);
 static CONF_MODULE *module_find(char *name);
-static int module_init(CONF_MODULE *pmod, char *name, char *value, CONF *cnf);
-static CONF_MODULE *module_load_dso(CONF *cnf, char *name, char *value, unsigned long flags);
+static int module_init(CONF_MODULE *pmod, char *name, char *value,
+                                          const CONF *cnf);
+static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
+                                                                       unsigned long flags);
 
 /* Main function: load modules from a CONF structure */
 
-int CONF_modules_load(CONF *cnf, char *appname, unsigned long flags)
+int CONF_modules_load(const CONF *cnf, const char *appname,
+                     unsigned long flags)
        {
        STACK_OF(CONF_VALUE) *values;
        CONF_VALUE *vl;
@@ -125,9 +130,11 @@ int CONF_modules_load(CONF *cnf, char *appname, unsigned long flags)
 
        int ret, i;
 
-       if (!cnf || !appname)
+       if (!cnf)
                return 1;
 
+       if (appname == NULL)
+               appname = "openssl_conf";
 
        vsection = NCONF_get_string(cnf, NULL, appname); 
 
@@ -155,26 +162,48 @@ int CONF_modules_load(CONF *cnf, char *appname, unsigned long flags)
 
        }
 
-int CONF_modules_load_file(char *filename, char *appname, unsigned long flags)
+int CONF_modules_load_file(const char *filename, const char *appname,
+                          unsigned long flags)
        {
+       char *file = NULL;
        CONF *conf = NULL;
        int ret = 0;
        conf = NCONF_new(NULL);
        if (!conf)
                goto err;
 
-       if (NCONF_load(conf, filename, NULL) <= 0)
+       if (filename == NULL)
+               {
+               file = CONF_get1_default_config_file();
+               if (!file)
+                       goto err;
+               }
+       else
+               file = (char *)filename;
+
+       if (NCONF_load(conf, file, NULL) <= 0)
+               {
+               if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
+                 (ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE))
+                       {
+                       ERR_clear_error();
+                       ret = 1;
+                       }
                goto err;
+               }
 
        ret = CONF_modules_load(conf, appname, flags);
 
        err:
+       if (filename == NULL)
+               OPENSSL_free(file);
        NCONF_free(conf);
 
        return ret;
        }
 
-static int module_run(CONF *cnf, char *name, char *value, unsigned long flags)
+static int module_run(const CONF *cnf, char *name, char *value,
+                     unsigned long flags)
        {
        CONF_MODULE *md;
        int ret;
@@ -182,7 +211,7 @@ static int module_run(CONF *cnf, char *name, char *value, unsigned long flags)
        md = module_find(name);
 
        /* Module not found: try to load DSO */
-       if (!md)
+       if (!md && !(flags & CONF_MFLAGS_NO_DSO))
                md = module_load_dso(cnf, name, value, flags);
 
        if (!md)
@@ -201,9 +230,9 @@ static int module_run(CONF *cnf, char *name, char *value, unsigned long flags)
                {
                if (!(flags & CONF_MFLAGS_SILENT))
                        {
-                       char rcode[10];
+                       char rcode[DECIMAL_SIZE(ret)+1];
                        CONFerr(CONF_F_CONF_MODULES_LOAD, CONF_R_MODULE_INITIALIZATION_ERROR);
-                       sprintf(rcode, "%-8d", ret);
+                       BIO_snprintf(rcode, sizeof rcode, "%-8d", ret);
                        ERR_add_error_data(6, "module=", name, ", value=", value, ", retcode=", rcode);
                        }
                }
@@ -212,7 +241,8 @@ static int module_run(CONF *cnf, char *name, char *value, unsigned long flags)
        }
 
 /* Load a module from a DSO */
-static CONF_MODULE *module_load_dso(CONF *cnf, char *name, char *value, unsigned long flags)
+static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
+                                   unsigned long flags)
        {
        DSO *dso = NULL;
        conf_init_func *ifunc;
@@ -224,7 +254,7 @@ static CONF_MODULE *module_load_dso(CONF *cnf, char *name, char *value, unsigned
        path = NCONF_get_string(cnf, value, "path");
        if (!path)
                {
-               ERR_get_error();
+               ERR_clear_error();
                path = name;
                }
        dso = DSO_load(NULL, path, NULL, 0);
@@ -240,11 +270,6 @@ static CONF_MODULE *module_load_dso(CONF *cnf, char *name, char *value, unsigned
                goto err;
                }
         ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name);
-       if (!ffunc)
-               {
-               errcode = CONF_R_MISSING_FINISH_FUNCTION;
-               goto err;
-               }
        /* All OK, add module */
        md = module_add(dso, name, ifunc, ffunc);
 
@@ -262,8 +287,8 @@ static CONF_MODULE *module_load_dso(CONF *cnf, char *name, char *value, unsigned
        }
 
 /* add module to list */
-static CONF_MODULE *module_add(DSO *dso, char *name,
-                       conf_init_func *ifunc, conf_finish_func *ffunc)
+static CONF_MODULE *module_add(DSO *dso, const char *name,
+                              conf_init_func *ifunc, conf_finish_func *ffunc)
        {
        CONF_MODULE *tmod = NULL;
        if (supported_modules == NULL)
@@ -318,9 +343,11 @@ static CONF_MODULE *module_find(char *name)
        }
 
 /* initialize a module */
-static int module_init(CONF_MODULE *pmod, char *name, char *value, CONF *cnf)
+static int module_init(CONF_MODULE *pmod, char *name, char *value,
+                      const CONF *cnf)
        {
-       int ret, init_called = 0;
+       int ret = 1;
+       int init_called = 0;
        CONF_IMODULE *imod = NULL;
 
        /* Otherwise add initialized module to list */
@@ -347,13 +374,20 @@ static int module_init(CONF_MODULE *pmod, char *name, char *value, CONF *cnf)
                }
 
        if (initialized_modules == NULL)
+               {
                initialized_modules = sk_CONF_IMODULE_new_null();
-
-       if (!initialized_modules)
-               goto err;
+               if (!initialized_modules)
+                       {
+                       CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               }
 
        if (!sk_CONF_IMODULE_push(initialized_modules, imod))
+               {
+               CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
                goto err;
+               }
 
        pmod->links++;
 
@@ -361,8 +395,6 @@ static int module_init(CONF_MODULE *pmod, char *name, char *value, CONF *cnf)
 
        err:
 
-       CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
-
        /* We've started the module so we'd better finish it */
        if (pmod->finish && init_called)
                pmod->finish(imod);
@@ -390,6 +422,7 @@ void CONF_modules_unload(int all)
        {
        int i;
        CONF_MODULE *md;
+       CONF_modules_finish();
        /* unload modules in reverse order */
        for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--)
                {
@@ -435,7 +468,8 @@ void CONF_modules_finish(void)
 
 static void module_finish(CONF_IMODULE *imod)
        {
-       imod->pmod->finish(imod);
+       if (imod->pmod->finish)
+               imod->pmod->finish(imod);
        imod->pmod->links--;
        OPENSSL_free(imod->name);
        OPENSSL_free(imod->value);
@@ -444,7 +478,8 @@ static void module_finish(CONF_IMODULE *imod)
 
 /* Add a static module to OpenSSL */
 
-int CONF_module_add(char *name, conf_init_func *ifunc, conf_finish_func *ffunc)
+int CONF_module_add(const char *name, conf_init_func *ifunc, 
+                   conf_finish_func *ffunc)
        {
        if (module_add(NULL, name, ifunc, ffunc))
                return 1;
@@ -460,17 +495,17 @@ void CONF_modules_free(void)
 
 /* Utility functions */
 
-char *CONF_imodule_get_name(CONF_IMODULE *md)
+const char *CONF_imodule_get_name(const CONF_IMODULE *md)
        {
        return md->name;
        }
 
-char *CONF_imodule_get_value(CONF_IMODULE *md)
+const char *CONF_imodule_get_value(const CONF_IMODULE *md)
        {
        return md->value;
        }
 
-void *CONF_imodule_get_usr_data(CONF_IMODULE *md)
+void *CONF_imodule_get_usr_data(const CONF_IMODULE *md)
        {
        return md->usr_data;
        }
@@ -480,12 +515,12 @@ void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data)
        md->usr_data = usr_data;
        }
 
-CONF_MODULE *CONF_imodule_get_module(CONF_IMODULE *md)
+CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md)
        {
        return md->pmod;
        }
 
-unsigned long CONF_imodule_get_flags(CONF_IMODULE *md)
+unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md)
        {
        return md->flags;
        }
@@ -505,3 +540,77 @@ void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
        pmod->usr_data = usr_data;
        }
 
+/* Return default config file name */
+
+char *CONF_get1_default_config_file(void)
+       {
+       char *file;
+       int len;
+
+       file = getenv("OPENSSL_CONF");
+       if (file) 
+               return BUF_strdup(file);
+
+       len = strlen(X509_get_default_cert_area());
+#ifndef OPENSSL_SYS_VMS
+       len++;
+#endif
+       len += strlen(OPENSSL_CONF);
+
+       file = OPENSSL_malloc(len + 1);
+
+       if (!file)
+               return NULL;
+       BUF_strlcpy(file,X509_get_default_cert_area(),len + 1);
+#ifndef OPENSSL_SYS_VMS
+       BUF_strlcat(file,"/",len + 1);
+#endif
+       BUF_strlcat(file,OPENSSL_CONF,len + 1);
+
+       return file;
+       }
+
+/* This function takes a list separated by 'sep' and calls the
+ * callback function giving the start and length of each member
+ * optionally stripping leading and trailing whitespace. This can
+ * be used to parse comma separated lists for example.
+ */
+
+int CONF_parse_list(const char *list_, int sep, int nospc,
+       int (*list_cb)(const char *elem, int len, void *usr), void *arg)
+       {
+       int ret;
+       const char *lstart, *tmpend, *p;
+       lstart = list_;
+
+       for(;;)
+               {
+               if (nospc)
+                       {
+                       while(*lstart && isspace((unsigned char)*lstart))
+                               lstart++;
+                       }
+               p = strchr(lstart, sep);
+               if (p == lstart || !*lstart)
+                       ret = list_cb(NULL, 0, arg);
+               else
+                       {
+                       if (p)
+                               tmpend = p - 1;
+                       else 
+                               tmpend = lstart + strlen(lstart) - 1;
+                       if (nospc)
+                               {
+                               while(isspace((unsigned char)*tmpend))
+                                       tmpend--;
+                               }
+                       ret = list_cb(lstart, tmpend - lstart + 1, arg);
+                       }
+               if (ret <= 0)
+                       return ret;
+               if (p == NULL)
+                       return 1;
+               lstart = p + 1;
+               }
+       }
+