diff options
Diffstat (limited to 'src/lib/libcrypto/engine/eng_dyn.c')
-rw-r--r-- | src/lib/libcrypto/engine/eng_dyn.c | 108 |
1 files changed, 98 insertions, 10 deletions
diff --git a/src/lib/libcrypto/engine/eng_dyn.c b/src/lib/libcrypto/engine/eng_dyn.c index 4139a16e76..acb30c34d8 100644 --- a/src/lib/libcrypto/engine/eng_dyn.c +++ b/src/lib/libcrypto/engine/eng_dyn.c | |||
@@ -57,11 +57,7 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | 59 | ||
60 | #include <stdio.h> | ||
61 | #include <openssl/crypto.h> | ||
62 | #include "cryptlib.h" | ||
63 | #include "eng_int.h" | 60 | #include "eng_int.h" |
64 | #include <openssl/engine.h> | ||
65 | #include <openssl/dso.h> | 61 | #include <openssl/dso.h> |
66 | 62 | ||
67 | /* Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE loader | 63 | /* Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE loader |
@@ -70,7 +66,7 @@ | |||
70 | /* Our ENGINE handlers */ | 66 | /* Our ENGINE handlers */ |
71 | static int dynamic_init(ENGINE *e); | 67 | static int dynamic_init(ENGINE *e); |
72 | static int dynamic_finish(ENGINE *e); | 68 | static int dynamic_finish(ENGINE *e); |
73 | static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); | 69 | static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); |
74 | /* Predeclare our context type */ | 70 | /* Predeclare our context type */ |
75 | typedef struct st_dynamic_data_ctx dynamic_data_ctx; | 71 | typedef struct st_dynamic_data_ctx dynamic_data_ctx; |
76 | /* The implementation for the important control command */ | 72 | /* The implementation for the important control command */ |
@@ -80,7 +76,9 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx); | |||
80 | #define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1) | 76 | #define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1) |
81 | #define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2) | 77 | #define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2) |
82 | #define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3) | 78 | #define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3) |
83 | #define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 4) | 79 | #define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4) |
80 | #define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5) | ||
81 | #define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6) | ||
84 | 82 | ||
85 | /* The constants used when creating the ENGINE */ | 83 | /* The constants used when creating the ENGINE */ |
86 | static const char *engine_dynamic_id = "dynamic"; | 84 | static const char *engine_dynamic_id = "dynamic"; |
@@ -102,6 +100,14 @@ static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = { | |||
102 | "LIST_ADD", | 100 | "LIST_ADD", |
103 | "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", | 101 | "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", |
104 | ENGINE_CMD_FLAG_NUMERIC}, | 102 | ENGINE_CMD_FLAG_NUMERIC}, |
103 | {DYNAMIC_CMD_DIR_LOAD, | ||
104 | "DIR_LOAD", | ||
105 | "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)", | ||
106 | ENGINE_CMD_FLAG_NUMERIC}, | ||
107 | {DYNAMIC_CMD_DIR_ADD, | ||
108 | "DIR_ADD", | ||
109 | "Adds a directory from which ENGINEs can be loaded", | ||
110 | ENGINE_CMD_FLAG_STRING}, | ||
105 | {DYNAMIC_CMD_LOAD, | 111 | {DYNAMIC_CMD_LOAD, |
106 | "LOAD", | 112 | "LOAD", |
107 | "Load up the ENGINE specified by other settings", | 113 | "Load up the ENGINE specified by other settings", |
@@ -136,12 +142,18 @@ struct st_dynamic_data_ctx | |||
136 | const char *DYNAMIC_F1; | 142 | const char *DYNAMIC_F1; |
137 | /* The symbol name for the "initialise ENGINE structure" function */ | 143 | /* The symbol name for the "initialise ENGINE structure" function */ |
138 | const char *DYNAMIC_F2; | 144 | const char *DYNAMIC_F2; |
145 | /* Whether to never use 'dirs', use 'dirs' as a fallback, or only use | ||
146 | * 'dirs' for loading. Default is to use 'dirs' as a fallback. */ | ||
147 | int dir_load; | ||
148 | /* A stack of directories from which ENGINEs could be loaded */ | ||
149 | STACK *dirs; | ||
139 | }; | 150 | }; |
140 | 151 | ||
141 | /* This is the "ex_data" index we obtain and reserve for use with our context | 152 | /* This is the "ex_data" index we obtain and reserve for use with our context |
142 | * structure. */ | 153 | * structure. */ |
143 | static int dynamic_ex_data_idx = -1; | 154 | static int dynamic_ex_data_idx = -1; |
144 | 155 | ||
156 | static void int_free_str(void *s) { OPENSSL_free(s); } | ||
145 | /* Because our ex_data element may or may not get allocated depending on whether | 157 | /* Because our ex_data element may or may not get allocated depending on whether |
146 | * a "first-use" occurs before the ENGINE is freed, we have a memory leak | 158 | * a "first-use" occurs before the ENGINE is freed, we have a memory leak |
147 | * problem to solve. We can't declare a "new" handler for the ex_data as we | 159 | * problem to solve. We can't declare a "new" handler for the ex_data as we |
@@ -161,6 +173,8 @@ static void dynamic_data_ctx_free_func(void *parent, void *ptr, | |||
161 | OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); | 173 | OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); |
162 | if(ctx->engine_id) | 174 | if(ctx->engine_id) |
163 | OPENSSL_free((void*)ctx->engine_id); | 175 | OPENSSL_free((void*)ctx->engine_id); |
176 | if(ctx->dirs) | ||
177 | sk_pop_free(ctx->dirs, int_free_str); | ||
164 | OPENSSL_free(ctx); | 178 | OPENSSL_free(ctx); |
165 | } | 179 | } |
166 | } | 180 | } |
@@ -175,7 +189,7 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) | |||
175 | c = OPENSSL_malloc(sizeof(dynamic_data_ctx)); | 189 | c = OPENSSL_malloc(sizeof(dynamic_data_ctx)); |
176 | if(!c) | 190 | if(!c) |
177 | { | 191 | { |
178 | ENGINEerr(ENGINE_F_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); | 192 | ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); |
179 | return 0; | 193 | return 0; |
180 | } | 194 | } |
181 | memset(c, 0, sizeof(dynamic_data_ctx)); | 195 | memset(c, 0, sizeof(dynamic_data_ctx)); |
@@ -188,6 +202,14 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) | |||
188 | c->list_add_value = 0; | 202 | c->list_add_value = 0; |
189 | c->DYNAMIC_F1 = "v_check"; | 203 | c->DYNAMIC_F1 = "v_check"; |
190 | c->DYNAMIC_F2 = "bind_engine"; | 204 | c->DYNAMIC_F2 = "bind_engine"; |
205 | c->dir_load = 1; | ||
206 | c->dirs = sk_new_null(); | ||
207 | if(!c->dirs) | ||
208 | { | ||
209 | ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); | ||
210 | OPENSSL_free(c); | ||
211 | return 0; | ||
212 | } | ||
191 | CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); | 213 | CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); |
192 | if((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, | 214 | if((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, |
193 | dynamic_ex_data_idx)) == NULL) | 215 | dynamic_ex_data_idx)) == NULL) |
@@ -290,7 +312,7 @@ static int dynamic_finish(ENGINE *e) | |||
290 | return 0; | 312 | return 0; |
291 | } | 313 | } |
292 | 314 | ||
293 | static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) | 315 | static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) |
294 | { | 316 | { |
295 | dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); | 317 | dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); |
296 | int initialised; | 318 | int initialised; |
@@ -346,6 +368,34 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) | |||
346 | return 1; | 368 | return 1; |
347 | case DYNAMIC_CMD_LOAD: | 369 | case DYNAMIC_CMD_LOAD: |
348 | return dynamic_load(e, ctx); | 370 | return dynamic_load(e, ctx); |
371 | case DYNAMIC_CMD_DIR_LOAD: | ||
372 | if((i < 0) || (i > 2)) | ||
373 | { | ||
374 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, | ||
375 | ENGINE_R_INVALID_ARGUMENT); | ||
376 | return 0; | ||
377 | } | ||
378 | ctx->dir_load = (int)i; | ||
379 | return 1; | ||
380 | case DYNAMIC_CMD_DIR_ADD: | ||
381 | /* a NULL 'p' or a string of zero-length is the same thing */ | ||
382 | if(!p || (strlen((const char *)p) < 1)) | ||
383 | { | ||
384 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, | ||
385 | ENGINE_R_INVALID_ARGUMENT); | ||
386 | return 0; | ||
387 | } | ||
388 | { | ||
389 | char *tmp_str = BUF_strdup(p); | ||
390 | if(!tmp_str) | ||
391 | { | ||
392 | ENGINEerr(ENGINE_F_DYNAMIC_CTRL, | ||
393 | ERR_R_MALLOC_FAILURE); | ||
394 | return 0; | ||
395 | } | ||
396 | sk_insert(ctx->dirs, tmp_str, -1); | ||
397 | } | ||
398 | return 1; | ||
349 | default: | 399 | default: |
350 | break; | 400 | break; |
351 | } | 401 | } |
@@ -353,16 +403,53 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) | |||
353 | return 0; | 403 | return 0; |
354 | } | 404 | } |
355 | 405 | ||
406 | static int int_load(dynamic_data_ctx *ctx) | ||
407 | { | ||
408 | int num, loop; | ||
409 | /* Unless told not to, try a direct load */ | ||
410 | if((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso, | ||
411 | ctx->DYNAMIC_LIBNAME, NULL, 0)) != NULL) | ||
412 | return 1; | ||
413 | /* If we're not allowed to use 'dirs' or we have none, fail */ | ||
414 | if(!ctx->dir_load || ((num = sk_num(ctx->dirs)) < 1)) | ||
415 | return 0; | ||
416 | for(loop = 0; loop < num; loop++) | ||
417 | { | ||
418 | const char *s = sk_value(ctx->dirs, loop); | ||
419 | char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s); | ||
420 | if(!merge) | ||
421 | return 0; | ||
422 | if(DSO_load(ctx->dynamic_dso, merge, NULL, 0)) | ||
423 | { | ||
424 | /* Found what we're looking for */ | ||
425 | OPENSSL_free(merge); | ||
426 | return 1; | ||
427 | } | ||
428 | OPENSSL_free(merge); | ||
429 | } | ||
430 | return 0; | ||
431 | } | ||
432 | |||
356 | static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) | 433 | static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) |
357 | { | 434 | { |
358 | ENGINE cpy; | 435 | ENGINE cpy; |
359 | dynamic_fns fns; | 436 | dynamic_fns fns; |
360 | 437 | ||
361 | if(!ctx->DYNAMIC_LIBNAME || ((ctx->dynamic_dso = DSO_load(NULL, | 438 | if(!ctx->dynamic_dso) |
362 | ctx->DYNAMIC_LIBNAME, NULL, 0)) == NULL)) | 439 | ctx->dynamic_dso = DSO_new(); |
440 | if(!ctx->DYNAMIC_LIBNAME) | ||
441 | { | ||
442 | if(!ctx->engine_id) | ||
443 | return 0; | ||
444 | ctx->DYNAMIC_LIBNAME = | ||
445 | DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id); | ||
446 | } | ||
447 | if(!int_load(ctx)) | ||
363 | { | 448 | { |
364 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, | 449 | ENGINEerr(ENGINE_F_DYNAMIC_LOAD, |
365 | ENGINE_R_DSO_NOT_FOUND); | 450 | ENGINE_R_DSO_NOT_FOUND); |
451 | DSO_free(ctx->dynamic_dso); | ||
452 | ctx->dynamic_dso = NULL; | ||
366 | return 0; | 453 | return 0; |
367 | } | 454 | } |
368 | /* We have to find a bind function otherwise it'll always end badly */ | 455 | /* We have to find a bind function otherwise it'll always end badly */ |
@@ -409,6 +496,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) | |||
409 | * engine.h, much of this would be simplified if each area of code | 496 | * engine.h, much of this would be simplified if each area of code |
410 | * provided its own "summary" structure of all related callbacks. It | 497 | * provided its own "summary" structure of all related callbacks. It |
411 | * would also increase opaqueness. */ | 498 | * would also increase opaqueness. */ |
499 | fns.static_state = ENGINE_get_static_state(); | ||
412 | fns.err_fns = ERR_get_implementation(); | 500 | fns.err_fns = ERR_get_implementation(); |
413 | fns.ex_data_fns = CRYPTO_get_ex_data_implementation(); | 501 | fns.ex_data_fns = CRYPTO_get_ex_data_implementation(); |
414 | CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb, | 502 | CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb, |