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, |
