X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=crypto%2Fengine%2Feng_dyn.c;h=807da7a5eb841c61f2edc9317a41a2558b5fc12a;hb=9d0397e9779524745018d03a8f938905898dfffb;hp=4139a16e76dcec990b8c2b087350e8db683a73b9;hpb=a6c6874a1a0e625985ee2708afc30b7be05bdacf;p=openssl.git diff --git a/crypto/engine/eng_dyn.c b/crypto/engine/eng_dyn.c index 4139a16e76..807da7a5eb 100644 --- a/crypto/engine/eng_dyn.c +++ b/crypto/engine/eng_dyn.c @@ -57,11 +57,7 @@ */ -#include -#include -#include "cryptlib.h" #include "eng_int.h" -#include #include /* Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE loader @@ -70,7 +66,7 @@ /* Our ENGINE handlers */ static int dynamic_init(ENGINE *e); static int dynamic_finish(ENGINE *e); -static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); /* Predeclare our context type */ typedef struct st_dynamic_data_ctx dynamic_data_ctx; /* The implementation for the important control command */ @@ -80,7 +76,9 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx); #define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1) #define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2) #define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3) -#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 4) +#define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4) +#define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5) +#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6) /* The constants used when creating the ENGINE */ static const char *engine_dynamic_id = "dynamic"; @@ -102,6 +100,14 @@ static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = { "LIST_ADD", "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)", ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_DIR_LOAD, + "DIR_LOAD", + "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)", + ENGINE_CMD_FLAG_NUMERIC}, + {DYNAMIC_CMD_DIR_ADD, + "DIR_ADD", + "Adds a directory from which ENGINEs can be loaded", + ENGINE_CMD_FLAG_STRING}, {DYNAMIC_CMD_LOAD, "LOAD", "Load up the ENGINE specified by other settings", @@ -136,12 +142,18 @@ struct st_dynamic_data_ctx const char *DYNAMIC_F1; /* The symbol name for the "initialise ENGINE structure" function */ const char *DYNAMIC_F2; + /* Whether to never use 'dirs', use 'dirs' as a fallback, or only use + * 'dirs' for loading. Default is to use 'dirs' as a fallback. */ + int dir_load; + /* A stack of directories from which ENGINEs could be loaded */ + STACK_OF(OPENSSL_STRING) *dirs; }; /* This is the "ex_data" index we obtain and reserve for use with our context * structure. */ static int dynamic_ex_data_idx = -1; +static void int_free_str(char *s) { OPENSSL_free(s); } /* Because our ex_data element may or may not get allocated depending on whether * a "first-use" occurs before the ENGINE is freed, we have a memory leak * 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, OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); if(ctx->engine_id) OPENSSL_free((void*)ctx->engine_id); + if(ctx->dirs) + sk_OPENSSL_STRING_pop_free(ctx->dirs, int_free_str); OPENSSL_free(ctx); } } @@ -175,7 +189,7 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) c = OPENSSL_malloc(sizeof(dynamic_data_ctx)); if(!c) { - ENGINEerr(ENGINE_F_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); + ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); return 0; } memset(c, 0, sizeof(dynamic_data_ctx)); @@ -188,6 +202,14 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) c->list_add_value = 0; c->DYNAMIC_F1 = "v_check"; c->DYNAMIC_F2 = "bind_engine"; + c->dir_load = 1; + c->dirs = sk_OPENSSL_STRING_new_null(); + if(!c->dirs) + { + ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE); + OPENSSL_free(c); + return 0; + } CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); if((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx)) == NULL) @@ -290,7 +312,7 @@ static int dynamic_finish(ENGINE *e) return 0; } -static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) +static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) { dynamic_data_ctx *ctx = dynamic_get_data_ctx(e); int initialised; @@ -346,6 +368,34 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) return 1; case DYNAMIC_CMD_LOAD: return dynamic_load(e, ctx); + case DYNAMIC_CMD_DIR_LOAD: + if((i < 0) || (i > 2)) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ENGINE_R_INVALID_ARGUMENT); + return 0; + } + ctx->dir_load = (int)i; + return 1; + case DYNAMIC_CMD_DIR_ADD: + /* a NULL 'p' or a string of zero-length is the same thing */ + if(!p || (strlen((const char *)p) < 1)) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ENGINE_R_INVALID_ARGUMENT); + return 0; + } + { + char *tmp_str = BUF_strdup(p); + if(!tmp_str) + { + ENGINEerr(ENGINE_F_DYNAMIC_CTRL, + ERR_R_MALLOC_FAILURE); + return 0; + } + sk_OPENSSL_STRING_insert(ctx->dirs, tmp_str, -1); + } + return 1; default: break; } @@ -353,16 +403,53 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) return 0; } +static int int_load(dynamic_data_ctx *ctx) + { + int num, loop; + /* Unless told not to, try a direct load */ + if((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso, + ctx->DYNAMIC_LIBNAME, NULL, 0)) != NULL) + return 1; + /* If we're not allowed to use 'dirs' or we have none, fail */ + if(!ctx->dir_load || (num = sk_OPENSSL_STRING_num(ctx->dirs)) < 1) + return 0; + for(loop = 0; loop < num; loop++) + { + const char *s = sk_OPENSSL_STRING_value(ctx->dirs, loop); + char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s); + if(!merge) + return 0; + if(DSO_load(ctx->dynamic_dso, merge, NULL, 0)) + { + /* Found what we're looking for */ + OPENSSL_free(merge); + return 1; + } + OPENSSL_free(merge); + } + return 0; + } + static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx) { ENGINE cpy; dynamic_fns fns; - if(!ctx->DYNAMIC_LIBNAME || ((ctx->dynamic_dso = DSO_load(NULL, - ctx->DYNAMIC_LIBNAME, NULL, 0)) == NULL)) + if(!ctx->dynamic_dso) + ctx->dynamic_dso = DSO_new(); + if(!ctx->DYNAMIC_LIBNAME) + { + if(!ctx->engine_id) + return 0; + ctx->DYNAMIC_LIBNAME = + DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id); + } + if(!int_load(ctx)) { ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND); + DSO_free(ctx->dynamic_dso); + ctx->dynamic_dso = NULL; return 0; } /* 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) * engine.h, much of this would be simplified if each area of code * provided its own "summary" structure of all related callbacks. It * would also increase opaqueness. */ + fns.static_state = ENGINE_get_static_state(); fns.err_fns = ERR_get_implementation(); fns.ex_data_fns = CRYPTO_get_ex_data_implementation(); CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb,