1 /* 2 * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "eng_local.h" 11 #include <openssl/conf.h> 12 13 /* #define ENGINE_CONF_DEBUG */ 14 15 /* ENGINE config module */ 16 17 static const char *skip_dot(const char *name) 18 { 19 const char *p = strchr(name, '.'); 20 21 if (p != NULL) 22 return p + 1; 23 return name; 24 } 25 26 static STACK_OF(ENGINE) *initialized_engines = NULL; 27 28 static int int_engine_init(ENGINE *e) 29 { 30 if (!ENGINE_init(e)) 31 return 0; 32 if (!initialized_engines) 33 initialized_engines = sk_ENGINE_new_null(); 34 if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e)) { 35 ENGINE_finish(e); 36 return 0; 37 } 38 return 1; 39 } 40 41 static int int_engine_configure(const char *name, const char *value, const CONF *cnf) 42 { 43 int i; 44 int ret = 0; 45 long do_init = -1; 46 STACK_OF(CONF_VALUE) *ecmds; 47 CONF_VALUE *ecmd = NULL; 48 const char *ctrlname, *ctrlvalue; 49 ENGINE *e = NULL; 50 int soft = 0; 51 52 name = skip_dot(name); 53 #ifdef ENGINE_CONF_DEBUG 54 fprintf(stderr, "Configuring engine %s\n", name); 55 #endif 56 /* Value is a section containing ENGINE commands */ 57 ecmds = NCONF_get_section(cnf, value); 58 59 if (!ecmds) { 60 ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, 61 ENGINE_R_ENGINE_SECTION_ERROR); 62 return 0; 63 } 64 65 for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) { 66 ecmd = sk_CONF_VALUE_value(ecmds, i); 67 ctrlname = skip_dot(ecmd->name); 68 ctrlvalue = ecmd->value; 69 #ifdef ENGINE_CONF_DEBUG 70 fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, 71 ctrlvalue); 72 #endif 73 74 /* First handle some special pseudo ctrls */ 75 76 /* Override engine name to use */ 77 if (strcmp(ctrlname, "engine_id") == 0) 78 name = ctrlvalue; 79 else if (strcmp(ctrlname, "soft_load") == 0) 80 soft = 1; 81 /* Load a dynamic ENGINE */ 82 else if (strcmp(ctrlname, "dynamic_path") == 0) { 83 e = ENGINE_by_id("dynamic"); 84 if (!e) 85 goto err; 86 if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0)) 87 goto err; 88 if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0)) 89 goto err; 90 if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) 91 goto err; 92 } 93 /* ... add other pseudos here ... */ 94 else { 95 /* 96 * At this point we need an ENGINE structural reference if we 97 * don't already have one. 98 */ 99 if (!e) { 100 e = ENGINE_by_id(name); 101 if (!e && soft) { 102 ERR_clear_error(); 103 return 1; 104 } 105 if (!e) 106 goto err; 107 } 108 /* 109 * Allow "EMPTY" to mean no value: this allows a valid "value" to 110 * be passed to ctrls of type NO_INPUT 111 */ 112 if (strcmp(ctrlvalue, "EMPTY") == 0) 113 ctrlvalue = NULL; 114 if (strcmp(ctrlname, "init") == 0) { 115 if (!NCONF_get_number_e(cnf, value, "init", &do_init)) 116 goto err; 117 if (do_init == 1) { 118 if (!int_engine_init(e)) 119 goto err; 120 } else if (do_init != 0) { 121 ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, 122 ENGINE_R_INVALID_INIT_VALUE); 123 goto err; 124 } 125 } else if (strcmp(ctrlname, "default_algorithms") == 0) { 126 if (!ENGINE_set_default_string(e, ctrlvalue)) 127 goto err; 128 } else if (!ENGINE_ctrl_cmd_string(e, ctrlname, ctrlvalue, 0)) 129 goto err; 130 } 131 132 } 133 if (e && (do_init == -1) && !int_engine_init(e)) { 134 ecmd = NULL; 135 goto err; 136 } 137 ret = 1; 138 err: 139 if (ret != 1) { 140 ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, 141 ENGINE_R_ENGINE_CONFIGURATION_ERROR); 142 if (ecmd) 143 ERR_add_error_data(6, "section=", ecmd->section, 144 ", name=", ecmd->name, 145 ", value=", ecmd->value); 146 } 147 ENGINE_free(e); 148 return ret; 149 } 150 151 static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf) 152 { 153 STACK_OF(CONF_VALUE) *elist; 154 CONF_VALUE *cval; 155 int i; 156 #ifdef ENGINE_CONF_DEBUG 157 fprintf(stderr, "Called engine module: name %s, value %s\n", 158 CONF_imodule_get_name(md), CONF_imodule_get_value(md)); 159 #endif 160 /* Value is a section containing ENGINEs to configure */ 161 elist = NCONF_get_section(cnf, CONF_imodule_get_value(md)); 162 163 if (!elist) { 164 ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT, 165 ENGINE_R_ENGINES_SECTION_ERROR); 166 return 0; 167 } 168 169 for (i = 0; i < sk_CONF_VALUE_num(elist); i++) { 170 cval = sk_CONF_VALUE_value(elist, i); 171 if (!int_engine_configure(cval->name, cval->value, cnf)) 172 return 0; 173 } 174 175 return 1; 176 } 177 178 static void int_engine_module_finish(CONF_IMODULE *md) 179 { 180 ENGINE *e; 181 182 while ((e = sk_ENGINE_pop(initialized_engines))) 183 ENGINE_finish(e); 184 sk_ENGINE_free(initialized_engines); 185 initialized_engines = NULL; 186 } 187 188 void ENGINE_add_conf_module(void) 189 { 190 CONF_module_add("engines", 191 int_engine_module_init, int_engine_module_finish); 192 } 193