eng_cnf.c revision 296341
1139747Simp/* eng_cnf.c */
24Srgrimes/*
34Srgrimes * Written by Stephen Henson (steve@openssl.org) for the OpenSSL project
44Srgrimes * 2001.
58876Srgrimes */
64Srgrimes/* ====================================================================
74Srgrimes * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
84Srgrimes *
94Srgrimes * Redistribution and use in source and binary forms, with or without
104Srgrimes * modification, are permitted provided that the following conditions
118876Srgrimes * are met:
128876Srgrimes *
134Srgrimes * 1. Redistributions of source code must retain the above copyright
144Srgrimes *    notice, this list of conditions and the following disclaimer.
158876Srgrimes *
164Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
178876Srgrimes *    notice, this list of conditions and the following disclaimer in
184Srgrimes *    the documentation and/or other materials provided with the
194Srgrimes *    distribution.
204Srgrimes *
214Srgrimes * 3. All advertising materials mentioning features or use of this
228876Srgrimes *    software must display the following acknowledgment:
234Srgrimes *    "This product includes software developed by the OpenSSL Project
244Srgrimes *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
254Srgrimes *
264Srgrimes * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
274Srgrimes *    endorse or promote products derived from this software without
284Srgrimes *    prior written permission. For written permission, please contact
294Srgrimes *    licensing@OpenSSL.org.
304Srgrimes *
31116176Sobrien * 5. Products derived from this software may not be called "OpenSSL"
32116176Sobrien *    nor may "OpenSSL" appear in their names without prior written
33116176Sobrien *    permission of the OpenSSL Project.
342056Swollman *
3547098Sbde * 6. Redistributions of any form whatsoever must retain the following
3612734Sbde *    acknowledgment:
372056Swollman *    "This product includes software developed by the OpenSSL Project
384Srgrimes *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
394Srgrimes *
404Srgrimes * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4192756Salfred * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
424Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4312515Sphk * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
444Srgrimes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4537504Sbde * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
464Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
474Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48137117Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49195699Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50195699Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51195699Srwatson * OF THE POSSIBILITY OF SUCH DAMAGE.
52195699Srwatson * ====================================================================
53195699Srwatson *
54195699Srwatson * This product includes cryptographic software written by Eric Young
554Srgrimes * (eay@cryptsoft.com).  This product includes software written by Tim
56131952Smarcel * Hudson (tjh@cryptsoft.com).
57131952Smarcel *
584Srgrimes */
5912515Sphk
60131952Smarcel#include "eng_int.h"
614Srgrimes#include <openssl/conf.h>
624Srgrimes
63131952Smarcel/* #define ENGINE_CONF_DEBUG */
644Srgrimes
654Srgrimes/* ENGINE config module */
664Srgrimes
67131952Smarcelstatic char *skip_dot(char *name)
68131952Smarcel{
69131952Smarcel    char *p;
70131952Smarcel    p = strchr(name, '.');
71131952Smarcel    if (p)
724Srgrimes        return p + 1;
73131952Smarcel    return name;
74131952Smarcel}
75131952Smarcel
76131952Smarcelstatic STACK_OF(ENGINE) *initialized_engines = NULL;
77131952Smarcel
784Srgrimesstatic int int_engine_init(ENGINE *e)
794Srgrimes{
804Srgrimes    if (!ENGINE_init(e))
814Srgrimes        return 0;
824Srgrimes    if (!initialized_engines)
834Srgrimes        initialized_engines = sk_ENGINE_new_null();
844Srgrimes    if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e)) {
85131952Smarcel        ENGINE_finish(e);
864Srgrimes        return 0;
874Srgrimes    }
884Srgrimes    return 1;
894Srgrimes}
90131952Smarcel
914Srgrimesstatic int int_engine_configure(char *name, char *value, const CONF *cnf)
92131952Smarcel{
934Srgrimes    int i;
944Srgrimes    int ret = 0;
95131952Smarcel    long do_init = -1;
96131952Smarcel    STACK_OF(CONF_VALUE) *ecmds;
974Srgrimes    CONF_VALUE *ecmd = NULL;
984Srgrimes    char *ctrlname, *ctrlvalue;
994Srgrimes    ENGINE *e = NULL;
1004Srgrimes    int soft = 0;
101131952Smarcel
1024Srgrimes    name = skip_dot(name);
103131952Smarcel#ifdef ENGINE_CONF_DEBUG
1044Srgrimes    fprintf(stderr, "Configuring engine %s\n", name);
1054Srgrimes#endif
106131952Smarcel    /* Value is a section containing ENGINE commands */
107131952Smarcel    ecmds = NCONF_get_section(cnf, value);
1084Srgrimes
109131952Smarcel    if (!ecmds) {
1104Srgrimes        ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
111131952Smarcel                  ENGINE_R_ENGINE_SECTION_ERROR);
112131952Smarcel        return 0;
113131952Smarcel    }
114131952Smarcel
115131952Smarcel    for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) {
1164Srgrimes        ecmd = sk_CONF_VALUE_value(ecmds, i);
1174Srgrimes        ctrlname = skip_dot(ecmd->name);
118131952Smarcel        ctrlvalue = ecmd->value;
119131952Smarcel#ifdef ENGINE_CONF_DEBUG
1204Srgrimes        fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname,
121131952Smarcel                ctrlvalue);
1224Srgrimes#endif
123131952Smarcel
124131952Smarcel        /* First handle some special pseudo ctrls */
125131952Smarcel
126131952Smarcel        /* Override engine name to use */
127131952Smarcel        if (!strcmp(ctrlname, "engine_id"))
1284Srgrimes            name = ctrlvalue;
1294Srgrimes        else if (!strcmp(ctrlname, "soft_load"))
1304Srgrimes            soft = 1;
131131952Smarcel        /* Load a dynamic ENGINE */
1324Srgrimes        else if (!strcmp(ctrlname, "dynamic_path")) {
1334Srgrimes            e = ENGINE_by_id("dynamic");
134131952Smarcel            if (!e)
135131952Smarcel                goto err;
1364Srgrimes            if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
1374Srgrimes                goto err;
1384Srgrimes            if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
139131952Smarcel                goto err;
140131952Smarcel            if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
1414Srgrimes                goto err;
1424Srgrimes        }
143131952Smarcel        /* ... add other pseudos here ... */
144131952Smarcel        else {
1454Srgrimes            /*
1464Srgrimes             * At this point we need an ENGINE structural reference if we
1474Srgrimes             * don't already have one.
1484Srgrimes             */
149131952Smarcel            if (!e) {
1504Srgrimes                e = ENGINE_by_id(name);
1514Srgrimes                if (!e && soft) {
152131952Smarcel                    ERR_clear_error();
153131952Smarcel                    return 1;
1544Srgrimes                }
155131952Smarcel                if (!e)
156131952Smarcel                    goto err;
1574Srgrimes            }
158131952Smarcel            /*
1594Srgrimes             * Allow "EMPTY" to mean no value: this allows a valid "value" to
160             * be passed to ctrls of type NO_INPUT
161             */
162            if (!strcmp(ctrlvalue, "EMPTY"))
163                ctrlvalue = NULL;
164            if (!strcmp(ctrlname, "init")) {
165                if (!NCONF_get_number_e(cnf, value, "init", &do_init))
166                    goto err;
167                if (do_init == 1) {
168                    if (!int_engine_init(e))
169                        goto err;
170                } else if (do_init != 0) {
171                    ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
172                              ENGINE_R_INVALID_INIT_VALUE);
173                    goto err;
174                }
175            } else if (!strcmp(ctrlname, "default_algorithms")) {
176                if (!ENGINE_set_default_string(e, ctrlvalue))
177                    goto err;
178            } else if (!ENGINE_ctrl_cmd_string(e, ctrlname, ctrlvalue, 0))
179                goto err;
180        }
181
182    }
183    if (e && (do_init == -1) && !int_engine_init(e)) {
184        ecmd = NULL;
185        goto err;
186    }
187    ret = 1;
188 err:
189    if (ret != 1) {
190        ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
191                  ENGINE_R_ENGINE_CONFIGURATION_ERROR);
192        if (ecmd)
193            ERR_add_error_data(6, "section=", ecmd->section,
194                               ", name=", ecmd->name,
195                               ", value=", ecmd->value);
196    }
197    if (e)
198        ENGINE_free(e);
199    return ret;
200}
201
202static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
203{
204    STACK_OF(CONF_VALUE) *elist;
205    CONF_VALUE *cval;
206    int i;
207#ifdef ENGINE_CONF_DEBUG
208    fprintf(stderr, "Called engine module: name %s, value %s\n",
209            CONF_imodule_get_name(md), CONF_imodule_get_value(md));
210#endif
211    /* Value is a section containing ENGINEs to configure */
212    elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
213
214    if (!elist) {
215        ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT,
216                  ENGINE_R_ENGINES_SECTION_ERROR);
217        return 0;
218    }
219
220    for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
221        cval = sk_CONF_VALUE_value(elist, i);
222        if (!int_engine_configure(cval->name, cval->value, cnf))
223            return 0;
224    }
225
226    return 1;
227}
228
229static void int_engine_module_finish(CONF_IMODULE *md)
230{
231    ENGINE *e;
232    while ((e = sk_ENGINE_pop(initialized_engines)))
233        ENGINE_finish(e);
234    sk_ENGINE_free(initialized_engines);
235    initialized_engines = NULL;
236}
237
238void ENGINE_add_conf_module(void)
239{
240    CONF_module_add("engines",
241                    int_engine_module_init, int_engine_module_finish);
242}
243