#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";
"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",
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 *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(void *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
OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME);
if(ctx->engine_id)
OPENSSL_free((void*)ctx->engine_id);
+ if(ctx->dirs)
+ sk_pop_free(ctx->dirs, int_free_str);
OPENSSL_free(ctx);
}
}
c->list_add_value = 0;
c->DYNAMIC_F1 = "v_check";
c->DYNAMIC_F2 = "bind_engine";
+ c->dir_load = 1;
+ c->dirs = sk_new_null();
+ if(!c->dirs)
+ {
+ ENGINEerr(ENGINE_F_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)
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_insert(ctx->dirs, tmp_str, -1);
+ }
+ return 1;
default:
break;
}
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_num(ctx->dirs)) < 1))
+ return 0;
+ for(loop = 0; loop < num; loop++)
+ {
+ const char *s = sk_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 */