Home | History | Annotate | Download | only in engine
      1 /* eng_cnf.c */
      2 /* Written by Stephen Henson (steve (at) openssl.org) for the OpenSSL
      3  * project 2001.
      4  */
      5 /* ====================================================================
      6  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in
     17  *    the documentation and/or other materials provided with the
     18  *    distribution.
     19  *
     20  * 3. All advertising materials mentioning features or use of this
     21  *    software must display the following acknowledgment:
     22  *    "This product includes software developed by the OpenSSL Project
     23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     24  *
     25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     26  *    endorse or promote products derived from this software without
     27  *    prior written permission. For written permission, please contact
     28  *    licensing (at) OpenSSL.org.
     29  *
     30  * 5. Products derived from this software may not be called "OpenSSL"
     31  *    nor may "OpenSSL" appear in their names without prior written
     32  *    permission of the OpenSSL Project.
     33  *
     34  * 6. Redistributions of any form whatsoever must retain the following
     35  *    acknowledgment:
     36  *    "This product includes software developed by the OpenSSL Project
     37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     38  *
     39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     50  * OF THE POSSIBILITY OF SUCH DAMAGE.
     51  * ====================================================================
     52  *
     53  * This product includes cryptographic software written by Eric Young
     54  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) cryptsoft.com).
     56  *
     57  */
     58 
     59 #include "eng_int.h"
     60 #include <openssl/conf.h>
     61 
     62 /* #define ENGINE_CONF_DEBUG */
     63 
     64 /* ENGINE config module */
     65 
     66 static char *skip_dot(char *name)
     67 	{
     68 	char *p;
     69 	p = strchr(name, '.');
     70 	if (p)
     71 		return p + 1;
     72 	return name;
     73 	}
     74 
     75 static STACK_OF(ENGINE) *initialized_engines = NULL;
     76 
     77 static int int_engine_init(ENGINE *e)
     78 	{
     79 	if (!ENGINE_init(e))
     80 		return 0;
     81 	if (!initialized_engines)
     82 		initialized_engines = sk_ENGINE_new_null();
     83 	if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e))
     84 		{
     85 		ENGINE_finish(e);
     86 		return 0;
     87 		}
     88 	return 1;
     89 	}
     90 
     91 
     92 static int int_engine_configure(char *name, char *value, const CONF *cnf)
     93 	{
     94 	int i;
     95 	int ret = 0;
     96 	long do_init = -1;
     97 	STACK_OF(CONF_VALUE) *ecmds;
     98 	CONF_VALUE *ecmd = NULL;
     99 	char *ctrlname, *ctrlvalue;
    100 	ENGINE *e = NULL;
    101 	int soft = 0;
    102 
    103 	name = skip_dot(name);
    104 #ifdef ENGINE_CONF_DEBUG
    105 	fprintf(stderr, "Configuring engine %s\n", name);
    106 #endif
    107 	/* Value is a section containing ENGINE commands */
    108 	ecmds = NCONF_get_section(cnf, value);
    109 
    110 	if (!ecmds)
    111 		{
    112 		ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR);
    113 		return 0;
    114 		}
    115 
    116 	for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++)
    117 		{
    118 		ecmd = sk_CONF_VALUE_value(ecmds, i);
    119 		ctrlname = skip_dot(ecmd->name);
    120 		ctrlvalue = ecmd->value;
    121 #ifdef ENGINE_CONF_DEBUG
    122 	fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue);
    123 #endif
    124 
    125 		/* First handle some special pseudo ctrls */
    126 
    127 		/* Override engine name to use */
    128 		if (!strcmp(ctrlname, "engine_id"))
    129 			name = ctrlvalue;
    130 		else if (!strcmp(ctrlname, "soft_load"))
    131 			soft = 1;
    132 		/* Load a dynamic ENGINE */
    133 		else if (!strcmp(ctrlname, "dynamic_path"))
    134 			{
    135 			e = ENGINE_by_id("dynamic");
    136 			if (!e)
    137 				goto err;
    138 			if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
    139 				goto err;
    140 			if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
    141 				goto err;
    142 			if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
    143 				goto err;
    144 			}
    145 		/* ... add other pseudos here ... */
    146 		else
    147 			{
    148 			/* At this point we need an ENGINE structural reference
    149 			 * if we don't already have one.
    150 			 */
    151 			if (!e)
    152 				{
    153 				e = ENGINE_by_id(name);
    154 				if (!e && soft)
    155 					{
    156 					ERR_clear_error();
    157 					return 1;
    158 					}
    159 				if (!e)
    160 					goto err;
    161 				}
    162 			/* Allow "EMPTY" to mean no value: this allows a valid
    163 			 * "value" to be passed to ctrls of type NO_INPUT
    164 		 	 */
    165 			if (!strcmp(ctrlvalue, "EMPTY"))
    166 				ctrlvalue = NULL;
    167 			if (!strcmp(ctrlname, "init"))
    168 				{
    169 				if (!NCONF_get_number_e(cnf, value, "init", &do_init))
    170 					goto err;
    171 				if (do_init == 1)
    172 					{
    173 					if (!int_engine_init(e))
    174 						goto err;
    175 					}
    176 				else if (do_init != 0)
    177 					{
    178 					ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_INVALID_INIT_VALUE);
    179 					goto err;
    180 					}
    181 				}
    182 			else if (!strcmp(ctrlname, "default_algorithms"))
    183 				{
    184 				if (!ENGINE_set_default_string(e, ctrlvalue))
    185 					goto err;
    186 				}
    187 			else if (!ENGINE_ctrl_cmd_string(e,
    188 					ctrlname, ctrlvalue, 0))
    189 				goto err;
    190 			}
    191 
    192 
    193 
    194 		}
    195 	if (e && (do_init == -1) && !int_engine_init(e))
    196 		{
    197 		ecmd = NULL;
    198 		goto err;
    199 		}
    200 	ret = 1;
    201 	err:
    202 	if (ret != 1)
    203 		{
    204 		ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_CONFIGURATION_ERROR);
    205 		if (ecmd)
    206 			ERR_add_error_data(6, "section=", ecmd->section,
    207 						", name=", ecmd->name,
    208 						", value=", ecmd->value);
    209 		}
    210 	if (e)
    211 		ENGINE_free(e);
    212 	return ret;
    213 	}
    214 
    215 
    216 static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
    217 	{
    218 	STACK_OF(CONF_VALUE) *elist;
    219 	CONF_VALUE *cval;
    220 	int i;
    221 #ifdef ENGINE_CONF_DEBUG
    222 	fprintf(stderr, "Called engine module: name %s, value %s\n",
    223 			CONF_imodule_get_name(md), CONF_imodule_get_value(md));
    224 #endif
    225 	/* Value is a section containing ENGINEs to configure */
    226 	elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
    227 
    228 	if (!elist)
    229 		{
    230 		ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT, ENGINE_R_ENGINES_SECTION_ERROR);
    231 		return 0;
    232 		}
    233 
    234 	for (i = 0; i < sk_CONF_VALUE_num(elist); i++)
    235 		{
    236 		cval = sk_CONF_VALUE_value(elist, i);
    237 		if (!int_engine_configure(cval->name, cval->value, cnf))
    238 			return 0;
    239 		}
    240 
    241 	return 1;
    242 	}
    243 
    244 static void int_engine_module_finish(CONF_IMODULE *md)
    245 	{
    246 	ENGINE *e;
    247 	while ((e = sk_ENGINE_pop(initialized_engines)))
    248 		ENGINE_finish(e);
    249 	sk_ENGINE_free(initialized_engines);
    250 	initialized_engines = NULL;
    251 	}
    252 
    253 
    254 void ENGINE_add_conf_module(void)
    255 	{
    256 	CONF_module_add("engines",
    257 			int_engine_module_init,
    258 			int_engine_module_finish);
    259 	}
    260