Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/openssl/src/crypto/engine/eng_dyn.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* | - | ||||||||||||
2 | * Copyright 2001-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_int.h" | - | ||||||||||||
11 | #include "internal/dso.h" | - | ||||||||||||
12 | #include <openssl/crypto.h> | - | ||||||||||||
13 | - | |||||||||||||
14 | /* | - | ||||||||||||
15 | * Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE | - | ||||||||||||
16 | * loader should implement the hook-up functions with the following | - | ||||||||||||
17 | * prototypes. | - | ||||||||||||
18 | */ | - | ||||||||||||
19 | - | |||||||||||||
20 | /* Our ENGINE handlers */ | - | ||||||||||||
21 | static int dynamic_init(ENGINE *e); | - | ||||||||||||
22 | static int dynamic_finish(ENGINE *e); | - | ||||||||||||
23 | static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, | - | ||||||||||||
24 | void (*f) (void)); | - | ||||||||||||
25 | /* Predeclare our context type */ | - | ||||||||||||
26 | typedef struct st_dynamic_data_ctx dynamic_data_ctx; | - | ||||||||||||
27 | /* The implementation for the important control command */ | - | ||||||||||||
28 | static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx); | - | ||||||||||||
29 | - | |||||||||||||
30 | #define DYNAMIC_CMD_SO_PATH ENGINE_CMD_BASE | - | ||||||||||||
31 | #define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1) | - | ||||||||||||
32 | #define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2) | - | ||||||||||||
33 | #define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3) | - | ||||||||||||
34 | #define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4) | - | ||||||||||||
35 | #define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5) | - | ||||||||||||
36 | #define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6) | - | ||||||||||||
37 | - | |||||||||||||
38 | /* The constants used when creating the ENGINE */ | - | ||||||||||||
39 | static const char *engine_dynamic_id = "dynamic"; | - | ||||||||||||
40 | static const char *engine_dynamic_name = "Dynamic engine loading support"; | - | ||||||||||||
41 | static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = { | - | ||||||||||||
42 | {DYNAMIC_CMD_SO_PATH, | - | ||||||||||||
43 | "SO_PATH", | - | ||||||||||||
44 | "Specifies the path to the new ENGINE shared library", | - | ||||||||||||
45 | ENGINE_CMD_FLAG_STRING}, | - | ||||||||||||
46 | {DYNAMIC_CMD_NO_VCHECK, | - | ||||||||||||
47 | "NO_VCHECK", | - | ||||||||||||
48 | "Specifies to continue even if version checking fails (boolean)", | - | ||||||||||||
49 | ENGINE_CMD_FLAG_NUMERIC}, | - | ||||||||||||
50 | {DYNAMIC_CMD_ID, | - | ||||||||||||
51 | "ID", | - | ||||||||||||
52 | "Specifies an ENGINE id name for loading", | - | ||||||||||||
53 | ENGINE_CMD_FLAG_STRING}, | - | ||||||||||||
54 | {DYNAMIC_CMD_LIST_ADD, | - | ||||||||||||
55 | "LIST_ADD", | - | ||||||||||||
56 | "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", | - | ||||||||||||
57 | ENGINE_CMD_FLAG_NUMERIC}, | - | ||||||||||||
58 | {DYNAMIC_CMD_DIR_LOAD, | - | ||||||||||||
59 | "DIR_LOAD", | - | ||||||||||||
60 | "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)", | - | ||||||||||||
61 | ENGINE_CMD_FLAG_NUMERIC}, | - | ||||||||||||
62 | {DYNAMIC_CMD_DIR_ADD, | - | ||||||||||||
63 | "DIR_ADD", | - | ||||||||||||
64 | "Adds a directory from which ENGINEs can be loaded", | - | ||||||||||||
65 | ENGINE_CMD_FLAG_STRING}, | - | ||||||||||||
66 | {DYNAMIC_CMD_LOAD, | - | ||||||||||||
67 | "LOAD", | - | ||||||||||||
68 | "Load up the ENGINE specified by other settings", | - | ||||||||||||
69 | ENGINE_CMD_FLAG_NO_INPUT}, | - | ||||||||||||
70 | {0, NULL, NULL, 0} | - | ||||||||||||
71 | }; | - | ||||||||||||
72 | - | |||||||||||||
73 | /* | - | ||||||||||||
74 | * Loading code stores state inside the ENGINE structure via the "ex_data" | - | ||||||||||||
75 | * element. We load all our state into a single structure and use that as a | - | ||||||||||||
76 | * single context in the "ex_data" stack. | - | ||||||||||||
77 | */ | - | ||||||||||||
78 | struct st_dynamic_data_ctx { | - | ||||||||||||
79 | /* The DSO object we load that supplies the ENGINE code */ | - | ||||||||||||
80 | DSO *dynamic_dso; | - | ||||||||||||
81 | /* | - | ||||||||||||
82 | * The function pointer to the version checking shared library function | - | ||||||||||||
83 | */ | - | ||||||||||||
84 | dynamic_v_check_fn v_check; | - | ||||||||||||
85 | /* | - | ||||||||||||
86 | * The function pointer to the engine-binding shared library function | - | ||||||||||||
87 | */ | - | ||||||||||||
88 | dynamic_bind_engine bind_engine; | - | ||||||||||||
89 | /* The default name/path for loading the shared library */ | - | ||||||||||||
90 | char *DYNAMIC_LIBNAME; | - | ||||||||||||
91 | /* Whether to continue loading on a version check failure */ | - | ||||||||||||
92 | int no_vcheck; | - | ||||||||||||
93 | /* If non-NULL, stipulates the 'id' of the ENGINE to be loaded */ | - | ||||||||||||
94 | char *engine_id; | - | ||||||||||||
95 | /* | - | ||||||||||||
96 | * If non-zero, a successfully loaded ENGINE should be added to the | - | ||||||||||||
97 | * internal ENGINE list. If 2, the add must succeed or the entire load | - | ||||||||||||
98 | * should fail. | - | ||||||||||||
99 | */ | - | ||||||||||||
100 | int list_add_value; | - | ||||||||||||
101 | /* The symbol name for the version checking function */ | - | ||||||||||||
102 | const char *DYNAMIC_F1; | - | ||||||||||||
103 | /* The symbol name for the "initialise ENGINE structure" function */ | - | ||||||||||||
104 | const char *DYNAMIC_F2; | - | ||||||||||||
105 | /* | - | ||||||||||||
106 | * Whether to never use 'dirs', use 'dirs' as a fallback, or only use | - | ||||||||||||
107 | * 'dirs' for loading. Default is to use 'dirs' as a fallback. | - | ||||||||||||
108 | */ | - | ||||||||||||
109 | int dir_load; | - | ||||||||||||
110 | /* A stack of directories from which ENGINEs could be loaded */ | - | ||||||||||||
111 | STACK_OF(OPENSSL_STRING) *dirs; | - | ||||||||||||
112 | }; | - | ||||||||||||
113 | - | |||||||||||||
114 | /* | - | ||||||||||||
115 | * This is the "ex_data" index we obtain and reserve for use with our context | - | ||||||||||||
116 | * structure. | - | ||||||||||||
117 | */ | - | ||||||||||||
118 | static int dynamic_ex_data_idx = -1; | - | ||||||||||||
119 | - | |||||||||||||
120 | static void int_free_str(char *s) | - | ||||||||||||
121 | { | - | ||||||||||||
122 | OPENSSL_free(s); | - | ||||||||||||
123 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
124 | - | |||||||||||||
125 | /* | - | ||||||||||||
126 | * Because our ex_data element may or may not get allocated depending on | - | ||||||||||||
127 | * whether a "first-use" occurs before the ENGINE is freed, we have a memory | - | ||||||||||||
128 | * leak problem to solve. We can't declare a "new" handler for the ex_data as | - | ||||||||||||
129 | * we don't want a dynamic_data_ctx in *all* ENGINE structures of all types | - | ||||||||||||
130 | * (this is a bug in the design of CRYPTO_EX_DATA). As such, we just declare | - | ||||||||||||
131 | * a "free" handler and that will get called if an ENGINE is being destroyed | - | ||||||||||||
132 | * and there was an ex_data element corresponding to our context type. | - | ||||||||||||
133 | */ | - | ||||||||||||
134 | static void dynamic_data_ctx_free_func(void *parent, void *ptr, | - | ||||||||||||
135 | CRYPTO_EX_DATA *ad, int idx, long argl, | - | ||||||||||||
136 | void *argp) | - | ||||||||||||
137 | { | - | ||||||||||||
138 | if (ptr) {
| 368 | ||||||||||||
139 | dynamic_data_ctx *ctx = (dynamic_data_ctx *)ptr; | - | ||||||||||||
140 | DSO_free(ctx->dynamic_dso); | - | ||||||||||||
141 | OPENSSL_free(ctx->DYNAMIC_LIBNAME); | - | ||||||||||||
142 | OPENSSL_free(ctx->engine_id); | - | ||||||||||||
143 | sk_OPENSSL_STRING_pop_free(ctx->dirs, int_free_str); | - | ||||||||||||
144 | OPENSSL_free(ctx); | - | ||||||||||||
145 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
146 | } executed 736 times by 1 test: end of block Executed by:
| 736 | ||||||||||||
147 | - | |||||||||||||
148 | /* | - | ||||||||||||
149 | * Construct the per-ENGINE context. We create it blindly and then use a lock | - | ||||||||||||
150 | * to check for a race - if so, all but one of the threads "racing" will have | - | ||||||||||||
151 | * wasted their time. The alternative involves creating everything inside the | - | ||||||||||||
152 | * lock which is far worse. | - | ||||||||||||
153 | */ | - | ||||||||||||
154 | static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) | - | ||||||||||||
155 | { | - | ||||||||||||
156 | dynamic_data_ctx *c = OPENSSL_zalloc(sizeof(*c)); | - | ||||||||||||
157 | int ret = 1; | - | ||||||||||||
158 | - | |||||||||||||
159 | if (c == NULL) {
| 0-368 | ||||||||||||
160 | ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE); | - | ||||||||||||
161 | return 0; never executed: return 0; | 0 | ||||||||||||
162 | } | - | ||||||||||||
163 | c->dirs = sk_OPENSSL_STRING_new_null(); | - | ||||||||||||
164 | if (c->dirs == NULL) {
| 0-368 | ||||||||||||
165 | ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE); | - | ||||||||||||
166 | OPENSSL_free(c); | - | ||||||||||||
167 | return 0; never executed: return 0; | 0 | ||||||||||||
168 | } | - | ||||||||||||
169 | c->DYNAMIC_F1 = "v_check"; | - | ||||||||||||
170 | c->DYNAMIC_F2 = "bind_engine"; | - | ||||||||||||
171 | c->dir_load = 1; | - | ||||||||||||
172 | CRYPTO_THREAD_write_lock(global_engine_lock); | - | ||||||||||||
173 | if ((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e,
| 0-368 | ||||||||||||
174 | dynamic_ex_data_idx))
| 0-368 | ||||||||||||
175 | == NULL) {
| 0-368 | ||||||||||||
176 | /* Good, we're the first */ | - | ||||||||||||
177 | ret = ENGINE_set_ex_data(e, dynamic_ex_data_idx, c); | - | ||||||||||||
178 | if (ret) {
| 0-368 | ||||||||||||
179 | *ctx = c; | - | ||||||||||||
180 | c = NULL; | - | ||||||||||||
181 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
182 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
183 | CRYPTO_THREAD_unlock(global_engine_lock); | - | ||||||||||||
184 | /* | - | ||||||||||||
185 | * If we lost the race to set the context, c is non-NULL and *ctx is the | - | ||||||||||||
186 | * context of the thread that won. | - | ||||||||||||
187 | */ | - | ||||||||||||
188 | if (c)
| 0-368 | ||||||||||||
189 | sk_OPENSSL_STRING_free(c->dirs); never executed: sk_OPENSSL_STRING_free(c->dirs); | 0 | ||||||||||||
190 | OPENSSL_free(c); | - | ||||||||||||
191 | return ret; executed 368 times by 1 test: return ret; Executed by:
| 368 | ||||||||||||
192 | } | - | ||||||||||||
193 | - | |||||||||||||
194 | /* | - | ||||||||||||
195 | * This function retrieves the context structure from an ENGINE's "ex_data", | - | ||||||||||||
196 | * or if it doesn't exist yet, sets it up. | - | ||||||||||||
197 | */ | - | ||||||||||||
198 | static dynamic_data_ctx *dynamic_get_data_ctx(ENGINE *e) | - | ||||||||||||
199 | { | - | ||||||||||||
200 | dynamic_data_ctx *ctx; | - | ||||||||||||
201 | if (dynamic_ex_data_idx < 0) {
| 368-1472 | ||||||||||||
202 | /* | - | ||||||||||||
203 | * Create and register the ENGINE ex_data, and associate our "free" | - | ||||||||||||
204 | * function with it to ensure any allocated contexts get freed when | - | ||||||||||||
205 | * an ENGINE goes underground. | - | ||||||||||||
206 | */ | - | ||||||||||||
207 | int new_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, | - | ||||||||||||
208 | dynamic_data_ctx_free_func); | - | ||||||||||||
209 | if (new_idx == -1) {
| 0-368 | ||||||||||||
210 | ENGINEerr(ENGINE_F_DYNAMIC_GET_DATA_CTX, ENGINE_R_NO_INDEX); | - | ||||||||||||
211 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||
212 | } | - | ||||||||||||
213 | CRYPTO_THREAD_write_lock(global_engine_lock); | - | ||||||||||||
214 | /* Avoid a race by checking again inside this lock */ | - | ||||||||||||
215 | if (dynamic_ex_data_idx < 0) {
| 0-368 | ||||||||||||
216 | /* Good, someone didn't beat us to it */ | - | ||||||||||||
217 | dynamic_ex_data_idx = new_idx; | - | ||||||||||||
218 | new_idx = -1; | - | ||||||||||||
219 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
220 | CRYPTO_THREAD_unlock(global_engine_lock); | - | ||||||||||||
221 | /* | - | ||||||||||||
222 | * In theory we could "give back" the index here if (new_idx>-1), but | - | ||||||||||||
223 | * it's not possible and wouldn't gain us much if it were. | - | ||||||||||||
224 | */ | - | ||||||||||||
225 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
226 | ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx); | - | ||||||||||||
227 | /* Check if the context needs to be created */ | - | ||||||||||||
228 | if ((ctx == NULL) && !dynamic_set_data_ctx(e, &ctx))
| 0-1472 | ||||||||||||
229 | /* "set_data" will set errors if necessary */ | - | ||||||||||||
230 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||
231 | return ctx; executed 1840 times by 1 test: return ctx; Executed by:
| 1840 | ||||||||||||
232 | } | - | ||||||||||||
233 | - | |||||||||||||
234 | static ENGINE *engine_dynamic(void) | - | ||||||||||||
235 | { | - | ||||||||||||
236 | ENGINE *ret = ENGINE_new(); | - | ||||||||||||
237 | if (ret == NULL)
| 0-1959 | ||||||||||||
238 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||
239 | if (!ENGINE_set_id(ret, engine_dynamic_id) ||
| 0-1959 | ||||||||||||
240 | !ENGINE_set_name(ret, engine_dynamic_name) ||
| 0-1959 | ||||||||||||
241 | !ENGINE_set_init_function(ret, dynamic_init) ||
| 0-1959 | ||||||||||||
242 | !ENGINE_set_finish_function(ret, dynamic_finish) ||
| 0-1959 | ||||||||||||
243 | !ENGINE_set_ctrl_function(ret, dynamic_ctrl) ||
| 0-1959 | ||||||||||||
244 | !ENGINE_set_flags(ret, ENGINE_FLAGS_BY_ID_COPY) ||
| 0-1959 | ||||||||||||
245 | !ENGINE_set_cmd_defns(ret, dynamic_cmd_defns)) {
| 0-1959 | ||||||||||||
246 | ENGINE_free(ret); | - | ||||||||||||
247 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||
248 | } | - | ||||||||||||
249 | return ret; executed 1959 times by 1 test: return ret; Executed by:
| 1959 | ||||||||||||
250 | } | - | ||||||||||||
251 | - | |||||||||||||
252 | void engine_load_dynamic_int(void) | - | ||||||||||||
253 | { | - | ||||||||||||
254 | ENGINE *toadd = engine_dynamic(); | - | ||||||||||||
255 | if (!toadd)
| 0-1959 | ||||||||||||
256 | return; never executed: return; | 0 | ||||||||||||
257 | ENGINE_add(toadd); | - | ||||||||||||
258 | /* | - | ||||||||||||
259 | * If the "add" worked, it gets a structural reference. So either way, we | - | ||||||||||||
260 | * release our just-created reference. | - | ||||||||||||
261 | */ | - | ||||||||||||
262 | ENGINE_free(toadd); | - | ||||||||||||
263 | /* | - | ||||||||||||
264 | * If the "add" didn't work, it was probably a conflict because it was | - | ||||||||||||
265 | * already added (eg. someone calling ENGINE_load_blah then calling | - | ||||||||||||
266 | * ENGINE_load_builtin_engines() perhaps). | - | ||||||||||||
267 | */ | - | ||||||||||||
268 | ERR_clear_error(); | - | ||||||||||||
269 | } executed 1959 times by 1 test: end of block Executed by:
| 1959 | ||||||||||||
270 | - | |||||||||||||
271 | static int dynamic_init(ENGINE *e) | - | ||||||||||||
272 | { | - | ||||||||||||
273 | /* | - | ||||||||||||
274 | * We always return failure - the "dynamic" engine itself can't be used | - | ||||||||||||
275 | * for anything. | - | ||||||||||||
276 | */ | - | ||||||||||||
277 | return 0; never executed: return 0; | 0 | ||||||||||||
278 | } | - | ||||||||||||
279 | - | |||||||||||||
280 | static int dynamic_finish(ENGINE *e) | - | ||||||||||||
281 | { | - | ||||||||||||
282 | /* | - | ||||||||||||
283 | * This should never be called on account of "dynamic_init" always | - | ||||||||||||
284 | * failing. | - | ||||||||||||
285 | */ | - | ||||||||||||
286 | return 0; never executed: return 0; | 0 | ||||||||||||
287 | } | - | ||||||||||||
288 | - | |||||||||||||
289 | static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) | - | ||||||||||||
290 | { | - | ||||||||||||
291 | dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); | - | ||||||||||||
292 | int initialised; | - | ||||||||||||
293 | - | |||||||||||||
294 | if (!ctx) {
| 0-1840 | ||||||||||||
295 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_NOT_LOADED); | - | ||||||||||||
296 | return 0; never executed: return 0; | 0 | ||||||||||||
297 | } | - | ||||||||||||
298 | initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1);
| 0-1840 | ||||||||||||
299 | /* All our control commands require the ENGINE to be uninitialised */ | - | ||||||||||||
300 | if (initialised) {
| 0-1840 | ||||||||||||
301 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED); | - | ||||||||||||
302 | return 0; never executed: return 0; | 0 | ||||||||||||
303 | } | - | ||||||||||||
304 | switch (cmd) { | - | ||||||||||||
305 | case DYNAMIC_CMD_SO_PATH: never executed: case 200: | 0 | ||||||||||||
306 | /* a NULL 'p' or a string of zero-length is the same thing */ | - | ||||||||||||
307 | if (p && (strlen((const char *)p) < 1))
| 0 | ||||||||||||
308 | p = NULL; never executed: p = ((void *)0) ; | 0 | ||||||||||||
309 | OPENSSL_free(ctx->DYNAMIC_LIBNAME); | - | ||||||||||||
310 | if (p)
| 0 | ||||||||||||
311 | ctx->DYNAMIC_LIBNAME = OPENSSL_strdup(p); never executed: ctx->DYNAMIC_LIBNAME = CRYPTO_strdup(p, __FILE__, 311); | 0 | ||||||||||||
312 | else | - | ||||||||||||
313 | ctx->DYNAMIC_LIBNAME = NULL; never executed: ctx->DYNAMIC_LIBNAME = ((void *)0) ; | 0 | ||||||||||||
314 | return (ctx->DYNAMIC_LIBNAME ? 1 : 0); never executed: return (ctx->DYNAMIC_LIBNAME ? 1 : 0);
| 0 | ||||||||||||
315 | case DYNAMIC_CMD_NO_VCHECK: never executed: case (200 + 1): | 0 | ||||||||||||
316 | ctx->no_vcheck = ((i == 0) ? 0 : 1);
| 0 | ||||||||||||
317 | return 1; never executed: return 1; | 0 | ||||||||||||
318 | case DYNAMIC_CMD_ID: executed 368 times by 1 test: case (200 + 2): Executed by:
| 368 | ||||||||||||
319 | /* a NULL 'p' or a string of zero-length is the same thing */ | - | ||||||||||||
320 | if (p && (strlen((const char *)p) < 1))
| 0-368 | ||||||||||||
321 | p = NULL; never executed: p = ((void *)0) ; | 0 | ||||||||||||
322 | OPENSSL_free(ctx->engine_id); | - | ||||||||||||
323 | if (p)
| 0-368 | ||||||||||||
324 | ctx->engine_id = OPENSSL_strdup(p); executed 368 times by 1 test: ctx->engine_id = CRYPTO_strdup(p, __FILE__, 324); Executed by:
| 368 | ||||||||||||
325 | else | - | ||||||||||||
326 | ctx->engine_id = NULL; never executed: ctx->engine_id = ((void *)0) ; | 0 | ||||||||||||
327 | return (ctx->engine_id ? 1 : 0); executed 368 times by 1 test: return (ctx->engine_id ? 1 : 0); Executed by:
| 0-368 | ||||||||||||
328 | case DYNAMIC_CMD_LIST_ADD: executed 368 times by 1 test: case (200 + 3): Executed by:
| 368 | ||||||||||||
329 | if ((i < 0) || (i > 2)) {
| 0-368 | ||||||||||||
330 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); | - | ||||||||||||
331 | return 0; never executed: return 0; | 0 | ||||||||||||
332 | } | - | ||||||||||||
333 | ctx->list_add_value = (int)i; | - | ||||||||||||
334 | return 1; executed 368 times by 1 test: return 1; Executed by:
| 368 | ||||||||||||
335 | case DYNAMIC_CMD_LOAD: executed 368 times by 1 test: case (200 + 6): Executed by:
| 368 | ||||||||||||
336 | return dynamic_load(e, ctx); executed 368 times by 1 test: return dynamic_load(e, ctx); Executed by:
| 368 | ||||||||||||
337 | case DYNAMIC_CMD_DIR_LOAD: executed 368 times by 1 test: case (200 + 4): Executed by:
| 368 | ||||||||||||
338 | if ((i < 0) || (i > 2)) {
| 0-368 | ||||||||||||
339 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); | - | ||||||||||||
340 | return 0; never executed: return 0; | 0 | ||||||||||||
341 | } | - | ||||||||||||
342 | ctx->dir_load = (int)i; | - | ||||||||||||
343 | return 1; executed 368 times by 1 test: return 1; Executed by:
| 368 | ||||||||||||
344 | case DYNAMIC_CMD_DIR_ADD: executed 368 times by 1 test: case (200 + 5): Executed by:
| 368 | ||||||||||||
345 | /* a NULL 'p' or a string of zero-length is the same thing */ | - | ||||||||||||
346 | if (!p || (strlen((const char *)p) < 1)) {
| 0-368 | ||||||||||||
347 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); | - | ||||||||||||
348 | return 0; never executed: return 0; | 0 | ||||||||||||
349 | } | - | ||||||||||||
350 | { | - | ||||||||||||
351 | char *tmp_str = OPENSSL_strdup(p); | - | ||||||||||||
352 | if (tmp_str == NULL) {
| 0-368 | ||||||||||||
353 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE); | - | ||||||||||||
354 | return 0; never executed: return 0; | 0 | ||||||||||||
355 | } | - | ||||||||||||
356 | if (!sk_OPENSSL_STRING_push(ctx->dirs, tmp_str)) {
| 0-368 | ||||||||||||
357 | OPENSSL_free(tmp_str); | - | ||||||||||||
358 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE); | - | ||||||||||||
359 | return 0; never executed: return 0; | 0 | ||||||||||||
360 | } | - | ||||||||||||
361 | } | - | ||||||||||||
362 | return 1; executed 368 times by 1 test: return 1; Executed by:
| 368 | ||||||||||||
363 | default: never executed: default: | 0 | ||||||||||||
364 | break; never executed: break; | 0 | ||||||||||||
365 | } | - | ||||||||||||
366 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); | - | ||||||||||||
367 | return 0; never executed: return 0; | 0 | ||||||||||||
368 | } | - | ||||||||||||
369 | - | |||||||||||||
370 | static int int_load(dynamic_data_ctx *ctx) | - | ||||||||||||
371 | { | - | ||||||||||||
372 | int num, loop; | - | ||||||||||||
373 | /* Unless told not to, try a direct load */ | - | ||||||||||||
374 | if ((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso,
| 0-368 | ||||||||||||
375 | ctx->DYNAMIC_LIBNAME, NULL,
| 0 | ||||||||||||
376 | 0)) != NULL)
| 0 | ||||||||||||
377 | return 1; never executed: return 1; | 0 | ||||||||||||
378 | /* If we're not allowed to use 'dirs' or we have none, fail */ | - | ||||||||||||
379 | if (!ctx->dir_load || (num = sk_OPENSSL_STRING_num(ctx->dirs)) < 1)
| 0-368 | ||||||||||||
380 | return 0; never executed: return 0; | 0 | ||||||||||||
381 | for (loop = 0; loop < num; loop++) {
| 0-368 | ||||||||||||
382 | const char *s = sk_OPENSSL_STRING_value(ctx->dirs, loop); | - | ||||||||||||
383 | char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s); | - | ||||||||||||
384 | if (!merge)
| 0-368 | ||||||||||||
385 | return 0; never executed: return 0; | 0 | ||||||||||||
386 | if (DSO_load(ctx->dynamic_dso, merge, NULL, 0)) {
| 0-368 | ||||||||||||
387 | /* Found what we're looking for */ | - | ||||||||||||
388 | OPENSSL_free(merge); | - | ||||||||||||
389 | return 1; executed 368 times by 1 test: return 1; Executed by:
| 368 | ||||||||||||
390 | } | - | ||||||||||||
391 | OPENSSL_free(merge); | - | ||||||||||||
392 | } never executed: end of block | 0 | ||||||||||||
393 | return 0; never executed: return 0; | 0 | ||||||||||||
394 | } | - | ||||||||||||
395 | - | |||||||||||||
396 | static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) | - | ||||||||||||
397 | { | - | ||||||||||||
398 | ENGINE cpy; | - | ||||||||||||
399 | dynamic_fns fns; | - | ||||||||||||
400 | - | |||||||||||||
401 | if (ctx->dynamic_dso == NULL)
| 0-368 | ||||||||||||
402 | ctx->dynamic_dso = DSO_new(); executed 368 times by 1 test: ctx->dynamic_dso = DSO_new(); Executed by:
| 368 | ||||||||||||
403 | if (ctx->dynamic_dso == NULL)
| 0-368 | ||||||||||||
404 | return 0; never executed: return 0; | 0 | ||||||||||||
405 | if (!ctx->DYNAMIC_LIBNAME) {
| 0-368 | ||||||||||||
406 | if (!ctx->engine_id)
| 0-368 | ||||||||||||
407 | return 0; never executed: return 0; | 0 | ||||||||||||
408 | DSO_ctrl(ctx->dynamic_dso, DSO_CTRL_SET_FLAGS, | - | ||||||||||||
409 | DSO_FLAG_NAME_TRANSLATION_EXT_ONLY, NULL); | - | ||||||||||||
410 | ctx->DYNAMIC_LIBNAME = | - | ||||||||||||
411 | DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id); | - | ||||||||||||
412 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
413 | if (!int_load(ctx)) {
| 0-368 | ||||||||||||
414 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND); | - | ||||||||||||
415 | DSO_free(ctx->dynamic_dso); | - | ||||||||||||
416 | ctx->dynamic_dso = NULL; | - | ||||||||||||
417 | return 0; never executed: return 0; | 0 | ||||||||||||
418 | } | - | ||||||||||||
419 | /* We have to find a bind function otherwise it'll always end badly */ | - | ||||||||||||
420 | if (!
| 0-368 | ||||||||||||
421 | (ctx->bind_engine =
| 0-368 | ||||||||||||
422 | (dynamic_bind_engine) DSO_bind_func(ctx->dynamic_dso,
| 0-368 | ||||||||||||
423 | ctx->DYNAMIC_F2))) {
| 0-368 | ||||||||||||
424 | ctx->bind_engine = NULL; | - | ||||||||||||
425 | DSO_free(ctx->dynamic_dso); | - | ||||||||||||
426 | ctx->dynamic_dso = NULL; | - | ||||||||||||
427 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_FAILURE); | - | ||||||||||||
428 | return 0; never executed: return 0; | 0 | ||||||||||||
429 | } | - | ||||||||||||
430 | /* Do we perform version checking? */ | - | ||||||||||||
431 | if (!ctx->no_vcheck) {
| 0-368 | ||||||||||||
432 | unsigned long vcheck_res = 0; | - | ||||||||||||
433 | /* | - | ||||||||||||
434 | * Now we try to find a version checking function and decide how to | - | ||||||||||||
435 | * cope with failure if/when it fails. | - | ||||||||||||
436 | */ | - | ||||||||||||
437 | ctx->v_check = | - | ||||||||||||
438 | (dynamic_v_check_fn) DSO_bind_func(ctx->dynamic_dso, | - | ||||||||||||
439 | ctx->DYNAMIC_F1); | - | ||||||||||||
440 | if (ctx->v_check)
| 0-368 | ||||||||||||
441 | vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION); executed 368 times by 1 test: vcheck_res = ctx->v_check((unsigned long)0x00030000); Executed by:
| 368 | ||||||||||||
442 | /* | - | ||||||||||||
443 | * We fail if the version checker veto'd the load *or* if it is | - | ||||||||||||
444 | * deferring to us (by returning its version) and we think it is too | - | ||||||||||||
445 | * old. | - | ||||||||||||
446 | */ | - | ||||||||||||
447 | if (vcheck_res < OSSL_DYNAMIC_OLDEST) {
| 0-368 | ||||||||||||
448 | /* Fail */ | - | ||||||||||||
449 | ctx->bind_engine = NULL; | - | ||||||||||||
450 | ctx->v_check = NULL; | - | ||||||||||||
451 | DSO_free(ctx->dynamic_dso); | - | ||||||||||||
452 | ctx->dynamic_dso = NULL; | - | ||||||||||||
453 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, | - | ||||||||||||
454 | ENGINE_R_VERSION_INCOMPATIBILITY); | - | ||||||||||||
455 | return 0; never executed: return 0; | 0 | ||||||||||||
456 | } | - | ||||||||||||
457 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
458 | /* | - | ||||||||||||
459 | * First binary copy the ENGINE structure so that we can roll back if the | - | ||||||||||||
460 | * hand-over fails | - | ||||||||||||
461 | */ | - | ||||||||||||
462 | memcpy(&cpy, e, sizeof(ENGINE)); | - | ||||||||||||
463 | /* | - | ||||||||||||
464 | * Provide the ERR, "ex_data", memory, and locking callbacks so the | - | ||||||||||||
465 | * loaded library uses our state rather than its own. FIXME: As noted in | - | ||||||||||||
466 | * engine.h, much of this would be simplified if each area of code | - | ||||||||||||
467 | * provided its own "summary" structure of all related callbacks. It | - | ||||||||||||
468 | * would also increase opaqueness. | - | ||||||||||||
469 | */ | - | ||||||||||||
470 | fns.static_state = ENGINE_get_static_state(); | - | ||||||||||||
471 | CRYPTO_get_mem_functions(&fns.mem_fns.malloc_fn, &fns.mem_fns.realloc_fn, | - | ||||||||||||
472 | &fns.mem_fns.free_fn); | - | ||||||||||||
473 | /* | - | ||||||||||||
474 | * Now that we've loaded the dynamic engine, make sure no "dynamic" | - | ||||||||||||
475 | * ENGINE elements will show through. | - | ||||||||||||
476 | */ | - | ||||||||||||
477 | engine_set_all_null(e); | - | ||||||||||||
478 | - | |||||||||||||
479 | /* Try to bind the ENGINE onto our own ENGINE structure */ | - | ||||||||||||
480 | if (!ctx->bind_engine(e, ctx->engine_id, &fns)) {
| 0-368 | ||||||||||||
481 | ctx->bind_engine = NULL; | - | ||||||||||||
482 | ctx->v_check = NULL; | - | ||||||||||||
483 | DSO_free(ctx->dynamic_dso); | - | ||||||||||||
484 | ctx->dynamic_dso = NULL; | - | ||||||||||||
485 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_INIT_FAILED); | - | ||||||||||||
486 | /* Copy the original ENGINE structure back */ | - | ||||||||||||
487 | memcpy(e, &cpy, sizeof(ENGINE)); | - | ||||||||||||
488 | return 0; never executed: return 0; | 0 | ||||||||||||
489 | } | - | ||||||||||||
490 | /* Do we try to add this ENGINE to the internal list too? */ | - | ||||||||||||
491 | if (ctx->list_add_value > 0) {
| 0-368 | ||||||||||||
492 | if (!ENGINE_add(e)) {
| 0-368 | ||||||||||||
493 | /* Do we tolerate this or fail? */ | - | ||||||||||||
494 | if (ctx->list_add_value > 1) {
| 0 | ||||||||||||
495 | /* | - | ||||||||||||
496 | * Fail - NB: By this time, it's too late to rollback, and | - | ||||||||||||
497 | * trying to do so allows the bind_engine() code to have | - | ||||||||||||
498 | * created leaks. We just have to fail where we are, after | - | ||||||||||||
499 | * the ENGINE has changed. | - | ||||||||||||
500 | */ | - | ||||||||||||
501 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, | - | ||||||||||||
502 | ENGINE_R_CONFLICTING_ENGINE_ID); | - | ||||||||||||
503 | return 0; never executed: return 0; | 0 | ||||||||||||
504 | } | - | ||||||||||||
505 | /* Tolerate */ | - | ||||||||||||
506 | ERR_clear_error(); | - | ||||||||||||
507 | } never executed: end of block | 0 | ||||||||||||
508 | } executed 368 times by 1 test: end of block Executed by:
| 368 | ||||||||||||
509 | return 1; executed 368 times by 1 test: return 1; Executed by:
| 368 | ||||||||||||
510 | } | - | ||||||||||||
Source code | Switch to Preprocessed file |