📄 eng_dyn.c
字号:
!ENGINE_set_finish_function(ret, dynamic_finish) || !ENGINE_set_ctrl_function(ret, dynamic_ctrl) || !ENGINE_set_flags(ret, ENGINE_FLAGS_BY_ID_COPY) || !ENGINE_set_cmd_defns(ret, dynamic_cmd_defns)) { ENGINE_free(ret); return NULL; } return ret; }void ENGINE_load_dynamic(void) { ENGINE *toadd = engine_dynamic(); if(!toadd) return; ENGINE_add(toadd); /* If the "add" worked, it gets a structural reference. So either way, * we release our just-created reference. */ ENGINE_free(toadd); /* If the "add" didn't work, it was probably a conflict because it was * already added (eg. someone calling ENGINE_load_blah then calling * ENGINE_load_builtin_engines() perhaps). */ ERR_clear_error(); }static int dynamic_init(ENGINE *e) { /* We always return failure - the "dyanamic" engine itself can't be used * for anything. */ return 0; }static int dynamic_finish(ENGINE *e) { /* This should never be called on account of "dynamic_init" always * failing. */ return 0; }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; if(!ctx) { ENGINEerr(ENGINE_F_DYNAMIC_CTRL,ENGINE_R_NOT_LOADED); return 0; } initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1); /* All our control commands require the ENGINE to be uninitialised */ if(initialised) { ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED); return 0; } switch(cmd) { case DYNAMIC_CMD_SO_PATH: /* a NULL 'p' or a string of zero-length is the same thing */ if(p && (strlen((const char *)p) < 1)) p = NULL; if(ctx->DYNAMIC_LIBNAME) OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME); if(p) ctx->DYNAMIC_LIBNAME = BUF_strdup(p); else ctx->DYNAMIC_LIBNAME = NULL; return (ctx->DYNAMIC_LIBNAME ? 1 : 0); case DYNAMIC_CMD_NO_VCHECK: ctx->no_vcheck = ((i == 0) ? 0 : 1); return 1; case DYNAMIC_CMD_ID: /* a NULL 'p' or a string of zero-length is the same thing */ if(p && (strlen((const char *)p) < 1)) p = NULL; if(ctx->engine_id) OPENSSL_free((void*)ctx->engine_id); if(p) ctx->engine_id = BUF_strdup(p); else ctx->engine_id = NULL; return (ctx->engine_id ? 1 : 0); case DYNAMIC_CMD_LIST_ADD: if((i < 0) || (i > 2)) { ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT); return 0; } ctx->list_add_value = (int)i; 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; } ENGINEerr(ENGINE_F_DYNAMIC_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); 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_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 */ if(!(ctx->bind_engine = (dynamic_bind_engine)DSO_bind_func( ctx->dynamic_dso, ctx->DYNAMIC_F2))) { ctx->bind_engine = NULL; DSO_free(ctx->dynamic_dso); ctx->dynamic_dso = NULL; ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_FAILURE); return 0; } /* Do we perform version checking? */ if(!ctx->no_vcheck) { unsigned long vcheck_res = 0; /* Now we try to find a version checking function and decide how * to cope with failure if/when it fails. */ ctx->v_check = (dynamic_v_check_fn)DSO_bind_func( ctx->dynamic_dso, ctx->DYNAMIC_F1); if(ctx->v_check) vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION); /* We fail if the version checker veto'd the load *or* if it is * deferring to us (by returning its version) and we think it is * too old. */ if(vcheck_res < OSSL_DYNAMIC_OLDEST) { /* Fail */ ctx->bind_engine = NULL; ctx->v_check = NULL; DSO_free(ctx->dynamic_dso); ctx->dynamic_dso = NULL; ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_VERSION_INCOMPATIBILITY); return 0; } } /* First binary copy the ENGINE structure so that we can roll back if * the hand-over fails */ memcpy(&cpy, e, sizeof(ENGINE)); /* Provide the ERR, "ex_data", memory, and locking callbacks so the * loaded library uses our state rather than its own. FIXME: As noted in * 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, &fns.mem_fns.realloc_cb, &fns.mem_fns.free_cb); fns.lock_fns.lock_locking_cb = CRYPTO_get_locking_callback(); fns.lock_fns.lock_add_lock_cb = CRYPTO_get_add_lock_callback(); fns.lock_fns.dynlock_create_cb = CRYPTO_get_dynlock_create_callback(); fns.lock_fns.dynlock_lock_cb = CRYPTO_get_dynlock_lock_callback(); fns.lock_fns.dynlock_destroy_cb = CRYPTO_get_dynlock_destroy_callback(); /* Now that we've loaded the dynamic engine, make sure no "dynamic" * ENGINE elements will show through. */ engine_set_all_null(e); /* Try to bind the ENGINE onto our own ENGINE structure */ if(!ctx->bind_engine(e, ctx->engine_id, &fns)) { ctx->bind_engine = NULL; ctx->v_check = NULL; DSO_free(ctx->dynamic_dso); ctx->dynamic_dso = NULL; ENGINEerr(ENGINE_F_DYNAMIC_LOAD,ENGINE_R_INIT_FAILED); /* Copy the original ENGINE structure back */ memcpy(e, &cpy, sizeof(ENGINE)); return 0; } /* Do we try to add this ENGINE to the internal list too? */ if(ctx->list_add_value > 0) { if(!ENGINE_add(e)) { /* Do we tolerate this or fail? */ if(ctx->list_add_value > 1) { /* Fail - NB: By this time, it's too late to * rollback, and trying to do so allows the * bind_engine() code to have created leaks. We * just have to fail where we are, after the * ENGINE has changed. */ ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_CONFLICTING_ENGINE_ID); return 0; } /* Tolerate */ ERR_clear_error(); } } return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -