Initial ENGINE config module, docs to follow.

Fix buffer overrun errors in OPENSSL_conf().
diff --git a/CHANGES b/CHANGES
index db838b0..a56411c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,9 @@
          *) applies to 0.9.6a/0.9.6b/0.9.6c and 0.9.7
          +) applies to 0.9.7 only
 
+  +) Prelminary ENGINE config module.
+     [Steve Henson]
+
   *) The earlier bugfix for the SSL3_ST_SW_HELLO_REQ_C case of
      ssl3_accept (ssl/s3_srvr.c) incorrectly used a local flag
      variable as an indication that a ClientHello message has been
diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h
index df84fa4..26452d4 100644
--- a/crypto/conf/conf.h
+++ b/crypto/conf/conf.h
@@ -188,6 +188,8 @@
 void *CONF_module_get_usr_data(CONF_MODULE *pmod);
 void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data);
 
+char *CONF_get1_default_config_file(void);
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c
index 3e752ac..814d5df 100644
--- a/crypto/conf/conf_mall.c
+++ b/crypto/conf/conf_mall.c
@@ -63,11 +63,13 @@
 #include <openssl/dso.h>
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
+#include <openssl/engine.h>
 
 void OPENSSL_load_builtin_modules(void)
 	{
 	/* Add builtin modules here */
 	ASN1_add_oid_module();
+	ENGINE_add_conf_module();
 	}
 
 /* This is the automatic configuration loader: it is called automatically by
@@ -77,32 +79,24 @@
 
 static int openssl_configured = 0;
 
-#if 0 /* Disabled because of obvious buffer overflow.
-       * This is not yet actually used anywhere -- but it shouldn't
-       * unless it is fixed first. */
 void OPENSSL_config(void)
 	{
-	char *file, config_name[256];
+	int ret;
+	char *file;
 	if (openssl_configured)
 		return;
 
 	OPENSSL_load_builtin_modules();
 
-	file = getenv("OPENSSL_CONF");
+	file = CONF_get1_default_config_file();
 	if (!file)
-                {
-		strcpy(config_name,X509_get_default_cert_area());
-#ifndef OPENSSL_SYS_VMS
-		strcat(config_name,"/");
-#endif
-		strcat(config_name,OPENSSL_CONF);
-		file=config_name;
-                }
+		return;
 
-	if(CONF_modules_load_file(file, "openssl_config", 0) <= 0)
+	ret = CONF_modules_load_file(file, "openssl_config", 0);
+	OPENSSL_free(file);
+	if (ret <= 0)
 		{
 		BIO *bio_err;
-
 		ERR_load_crypto_strings();
 		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
 			{
@@ -116,7 +110,6 @@
 	return;
 
 	}
-#endif
 
 void OPENSSL_no_config()
 	{
diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
index e2e357f..234eb7a 100644
--- a/crypto/conf/conf_mod.c
+++ b/crypto/conf/conf_mod.c
@@ -520,3 +520,32 @@
 	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;
+	strcpy(file,X509_get_default_cert_area());
+#ifndef OPENSSL_SYS_VMS
+	strcat(file,"/");
+#endif
+	strcat(file,OPENSSL_CONF);
+
+	return file;
+	}
diff --git a/crypto/engine/Makefile.ssl b/crypto/engine/Makefile.ssl
index de82b08..4b0ae05 100644
--- a/crypto/engine/Makefile.ssl
+++ b/crypto/engine/Makefile.ssl
@@ -26,13 +26,13 @@
 LIBSRC= eng_err.c eng_lib.c eng_list.c eng_init.c eng_ctrl.c \
 	eng_table.c eng_pkey.c eng_fat.c eng_all.c \
 	tb_rsa.c tb_dsa.c tb_dh.c tb_rand.c tb_cipher.c tb_digest.c \
-	eng_openssl.c eng_dyn.c \
+	eng_openssl.c eng_dyn.c eng_cnf.c \
 	hw_atalla.c hw_cswift.c hw_ncipher.c hw_nuron.c hw_ubsec.c \
 	hw_openbsd_dev_crypto.c
 LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
 	eng_table.o eng_pkey.o eng_fat.o eng_all.o \
 	tb_rsa.o tb_dsa.o tb_dh.o tb_rand.o tb_cipher.o tb_digest.o \
-	eng_openssl.o eng_dyn.o \
+	eng_openssl.o eng_dyn.o eng_cnf.o \
 	hw_atalla.o hw_cswift.o hw_ncipher.o hw_nuron.o hw_ubsec.o \
 	hw_openbsd_dev_crypto.o
 
diff --git a/crypto/engine/eng_cnf.c b/crypto/engine/eng_cnf.c
new file mode 100644
index 0000000..8e3f894
--- /dev/null
+++ b/crypto/engine/eng_cnf.c
@@ -0,0 +1,187 @@
+/* eng_cnf.c */
+/* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+
+/* #define ENGINE_CONF_DEBUG */
+
+/* ENGINE config module */
+
+static char *skip_dot(char *name)
+	{
+	char *p;
+	p = strchr(name, '.');
+	if (p)
+		return p + 1;
+	return name;
+	}
+
+int int_engine_configure(char *name, char *value, const CONF *cnf)
+	{
+	int i;
+	int ret = 0;
+	STACK_OF(CONF_VALUE) *ecmds;
+	CONF_VALUE *ecmd;
+	char *ctrlname, *ctrlvalue;
+	ENGINE *e = NULL;
+	name = skip_dot(name);
+#ifdef ENGINE_CONF_DEBUG
+	fprintf(stderr, "Configuring engine %s\n", name);
+#endif
+	/* Value is a section containing ENGINE commands */
+	ecmds = NCONF_get_section(cnf, value);
+
+	if (!ecmds)
+		{
+		ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR);
+		return 0;
+		}
+
+	for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++)
+		{
+		ecmd = sk_CONF_VALUE_value(ecmds, i);
+		ctrlname = skip_dot(ecmd->name);
+		ctrlvalue = ecmd->value;
+#ifdef ENGINE_CONF_DEBUG
+	fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue);
+#endif
+
+		/* First handle some special pseudo ctrls */
+
+		/* Override engine name to use */
+		if (!strcmp(ctrlname, "engine_id"))
+			name = ctrlvalue;
+		/* Load a dynamic ENGINE */
+		else if (!strcmp(ctrlname, "dynamic_path"))
+			{
+			e = ENGINE_by_id("dynamic");
+			if (!e)
+				goto err;
+			if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
+				goto err;
+			if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
+				goto err;
+			}
+		/* ... add other pseudos here ... */
+		else
+			{
+			/* At this point we need an ENGINE structural reference
+			 * if we don't already have one.
+			 */
+			if (!e)
+				{
+				e = ENGINE_by_id(name);
+				if (!e)
+					return 0;
+				}
+			/* Allow "EMPTY" to mean no value: this allows a valid
+			 * "value" to be passed to ctrls of type NO_INPUT
+		 	 */
+			if (!strcmp(ctrlvalue, "EMPTY"))
+				ctrlvalue = NULL;
+			if (!ENGINE_ctrl_cmd_string(e,
+					ctrlname, ctrlvalue, 0))
+				return 0;
+			}
+
+
+		}
+	ret = 1;
+	err:
+	if (e)
+		ENGINE_free(e);
+	return ret;
+	}
+	
+
+static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
+	{
+	STACK_OF(CONF_VALUE) *elist;
+	CONF_VALUE *cval;
+	int i;
+#ifdef ENGINE_CONF_DEBUG
+	fprintf(stderr, "Called engine module: name %s, value %s\n",
+			CONF_imodule_get_name(md), CONF_imodule_get_value(md));
+#endif
+	/* Value is a section containing ENGINEs to configure */
+	elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
+
+	if (!elist)
+		{
+		ENGINEerr(ENGINE_F_ENGINE_MODULE_INIT, ENGINE_R_ENGINES_SECTION_ERROR);
+		return 0;
+		}
+
+	for (i = 0; i < sk_CONF_VALUE_num(elist); i++)
+		{
+		cval = sk_CONF_VALUE_value(elist, i);
+		if (!int_engine_configure(cval->name, cval->value, cnf))
+			return 0;
+		}
+
+	return 1;
+	}
+
+void ENGINE_add_conf_module(void)
+	{
+	CONF_module_add("engines", int_engine_module_init, 0);
+	}
diff --git a/crypto/engine/eng_err.c b/crypto/engine/eng_err.c
index 2fe4c05..f3c0c35 100644
--- a/crypto/engine/eng_err.c
+++ b/crypto/engine/eng_err.c
@@ -87,6 +87,7 @@
 {ERR_PACK(0,ENGINE_F_ENGINE_LIST_REMOVE,0),	"ENGINE_LIST_REMOVE"},
 {ERR_PACK(0,ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,0),	"ENGINE_load_private_key"},
 {ERR_PACK(0,ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,0),	"ENGINE_load_public_key"},
+{ERR_PACK(0,ENGINE_F_ENGINE_MODULE_INIT,0),	"ENGINE_MODULE_INIT"},
 {ERR_PACK(0,ENGINE_F_ENGINE_NEW,0),	"ENGINE_new"},
 {ERR_PACK(0,ENGINE_F_ENGINE_REMOVE,0),	"ENGINE_remove"},
 {ERR_PACK(0,ENGINE_F_ENGINE_SET_DEFAULT_TYPE,0),	"ENGINE_SET_DEFAULT_TYPE"},
@@ -95,6 +96,7 @@
 {ERR_PACK(0,ENGINE_F_ENGINE_TABLE_REGISTER,0),	"ENGINE_TABLE_REGISTER"},
 {ERR_PACK(0,ENGINE_F_ENGINE_UNLOAD_KEY,0),	"ENGINE_UNLOAD_KEY"},
 {ERR_PACK(0,ENGINE_F_INT_CTRL_HELPER,0),	"INT_CTRL_HELPER"},
+{ERR_PACK(0,ENGINE_F_INT_ENGINE_CONFIGURE,0),	"INT_ENGINE_CONFIGURE"},
 {ERR_PACK(0,ENGINE_F_LOG_MESSAGE,0),	"LOG_MESSAGE"},
 {ERR_PACK(0,ENGINE_F_SET_DATA_CTX,0),	"SET_DATA_CTX"},
 {0,NULL}
@@ -118,7 +120,9 @@
 {ENGINE_R_DSO_FAILURE                    ,"DSO failure"},
 {ENGINE_R_DSO_FUNCTION_NOT_FOUND         ,"dso function not found"},
 {ENGINE_R_DSO_NOT_FOUND                  ,"dso not found"},
+{ENGINE_R_ENGINES_SECTION_ERROR          ,"engines section error"},
 {ENGINE_R_ENGINE_IS_NOT_IN_LIST          ,"engine is not in the list"},
+{ENGINE_R_ENGINE_SECTION_ERROR           ,"engine section error"},
 {ENGINE_R_FAILED_LOADING_PRIVATE_KEY     ,"failed loading private key"},
 {ENGINE_R_FAILED_LOADING_PUBLIC_KEY      ,"failed loading public key"},
 {ENGINE_R_FINISH_FAILED                  ,"finish failed"},
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c
index c76e6ad..0c22055 100644
--- a/crypto/engine/eng_list.c
+++ b/crypto/engine/eng_list.c
@@ -374,7 +374,10 @@
 		}
 	CRYPTO_r_unlock(CRYPTO_LOCK_ENGINE);
 	if(iterator == NULL)
+		{
 		ENGINEerr(ENGINE_F_ENGINE_BY_ID,
 			ENGINE_R_NO_SUCH_ENGINE);
+		ERR_add_error_data(2, "id=", id);
+		}
 	return iterator;
 	}
diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h
index 782d85a..291841a 100644
--- a/crypto/engine/engine.h
+++ b/crypto/engine/engine.h
@@ -517,6 +517,8 @@
  * selective functions. */
 int ENGINE_set_default(ENGINE *e, unsigned int flags);
 
+void ENGINE_add_conf_module(void);
+
 /* Deprecated functions ... */
 /* int ENGINE_clear_defaults(void); */
 
@@ -622,7 +624,6 @@
  * made after this point may be overwritten when the script is next run.
  */
 void ERR_load_ENGINE_strings(void);
-
 /* Error codes for the ENGINE functions. */
 
 /* Function codes. */
@@ -647,6 +648,7 @@
 #define ENGINE_F_ENGINE_LIST_REMOVE			 121
 #define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY		 150
 #define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY			 151
+#define ENGINE_F_ENGINE_MODULE_INIT			 187
 #define ENGINE_F_ENGINE_NEW				 122
 #define ENGINE_F_ENGINE_REMOVE				 123
 #define ENGINE_F_ENGINE_SET_DEFAULT_TYPE		 126
@@ -655,6 +657,7 @@
 #define ENGINE_F_ENGINE_TABLE_REGISTER			 184
 #define ENGINE_F_ENGINE_UNLOAD_KEY			 152
 #define ENGINE_F_INT_CTRL_HELPER			 172
+#define ENGINE_F_INT_ENGINE_CONFIGURE			 188
 #define ENGINE_F_LOG_MESSAGE				 141
 #define ENGINE_F_SET_DATA_CTX				 183
 
@@ -675,7 +678,9 @@
 #define ENGINE_R_DSO_FAILURE				 104
 #define ENGINE_R_DSO_FUNCTION_NOT_FOUND			 131
 #define ENGINE_R_DSO_NOT_FOUND				 132
+#define ENGINE_R_ENGINES_SECTION_ERROR			 148
 #define ENGINE_R_ENGINE_IS_NOT_IN_LIST			 105
+#define ENGINE_R_ENGINE_SECTION_ERROR			 149
 #define ENGINE_R_FAILED_LOADING_PRIVATE_KEY		 128
 #define ENGINE_R_FAILED_LOADING_PUBLIC_KEY		 129
 #define ENGINE_R_FINISH_FAILED				 106