X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fdso%2Fdso_lib.c;h=8a15b794abef2b2d5c97040e6c49c19638a8fb82;hp=9430d0d76f6edc03c831b3e197a4e9dbe53b65ee;hb=d0666f289ac013094bbbf547bfbcd616199b7d2d;hpb=51175595b32cf1c32b1c09e644f279a05fbcb2ba diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 9430d0d76f..8a15b794ab 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -1,4 +1,4 @@ -/* dso_lib.c */ +/* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -100,19 +100,19 @@ DSO *DSO_new_method(DSO_METHOD *meth) * to stealing the "best available" method. Will fallback * to DSO_METH_null() in the worst case. */ default_DSO_meth = DSO_METHOD_openssl(); - ret = (DSO *)Malloc(sizeof(DSO)); + ret = (DSO *)OPENSSL_malloc(sizeof(DSO)); if(ret == NULL) { DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE); return(NULL); } memset(ret, 0, sizeof(DSO)); - ret->meth_data = sk_new(NULL); - if((ret->meth_data = sk_new(NULL)) == NULL) + ret->meth_data = sk_void_new_null(); + if(ret->meth_data == NULL) { /* sk_new doesn't generate any errors so we do */ DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE); - Free(ret); + OPENSSL_free(ret); return(NULL); } if(meth == NULL) @@ -122,7 +122,7 @@ DSO *DSO_new_method(DSO_METHOD *meth) ret->references = 1; if((ret->meth->init != NULL) && !ret->meth->init(ret)) { - Free(ret); + OPENSSL_free(ret); ret=NULL; } return(ret); @@ -163,9 +163,13 @@ int DSO_free(DSO *dso) return(0); } - sk_free(dso->meth_data); + sk_void_free(dso->meth_data); + if(dso->filename != NULL) + OPENSSL_free(dso->filename); + if(dso->loaded_filename != NULL) + OPENSSL_free(dso->loaded_filename); - Free(dso); + OPENSSL_free(dso); return(1); } @@ -175,11 +179,11 @@ int DSO_flags(DSO *dso) } -int DSO_up(DSO *dso) +int DSO_up_ref(DSO *dso) { if (dso == NULL) { - DSOerr(DSO_F_DSO_UP,ERR_R_PASSED_NULL_PARAMETER); + DSOerr(DSO_F_DSO_UP_REF,ERR_R_PASSED_NULL_PARAMETER); return(0); } @@ -187,65 +191,293 @@ int DSO_up(DSO *dso) return(1); } -DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth) +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags) { DSO *ret; int allocated = 0; - if(filename == NULL) - { - DSOerr(DSO_F_DSO_LOAD,ERR_R_PASSED_NULL_PARAMETER); - return(NULL); - } if(dso == NULL) { ret = DSO_new_method(meth); if(ret == NULL) { DSOerr(DSO_F_DSO_LOAD,ERR_R_MALLOC_FAILURE); - return(NULL); + goto err; } allocated = 1; + /* Pass the provided flags to the new DSO object */ + if(DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_CTRL_FAILED); + goto err; + } } else ret = dso; + /* Don't load if we're currently already loaded */ + if(ret->filename != NULL) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_DSO_ALREADY_LOADED); + goto err; + } + /* filename can only be NULL if we were passed a dso that already has + * one set. */ + if(filename != NULL) + if(!DSO_set_filename(ret, filename)) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_SET_FILENAME_FAILED); + goto err; + } + filename = ret->filename; + if(filename == NULL) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_NO_FILENAME); + goto err; + } if(ret->meth->dso_load == NULL) { DSOerr(DSO_F_DSO_LOAD,DSO_R_UNSUPPORTED); - if(allocated) - DSO_free(ret); - return(NULL); + goto err; } - if(!ret->meth->dso_load(ret, filename)) + if(!ret->meth->dso_load(ret)) { DSOerr(DSO_F_DSO_LOAD,DSO_R_LOAD_FAILED); - if(allocated) - DSO_free(ret); - return(NULL); + goto err; } /* Load succeeded */ return(ret); +err: + if(allocated) + DSO_free(ret); + return(NULL); } -void *DSO_bind(DSO *dso, const char *symname) +void *DSO_bind_var(DSO *dso, const char *symname) { void *ret = NULL; if((dso == NULL) || (symname == NULL)) { - DSOerr(DSO_F_DSO_BIND,ERR_R_PASSED_NULL_PARAMETER); + DSOerr(DSO_F_DSO_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(dso->meth->dso_bind_var == NULL) + { + DSOerr(DSO_F_DSO_BIND_VAR,DSO_R_UNSUPPORTED); + return(NULL); + } + if((ret = dso->meth->dso_bind_var(dso, symname)) == NULL) + { + DSOerr(DSO_F_DSO_BIND_VAR,DSO_R_SYM_FAILURE); + return(NULL); + } + /* Success */ + return(ret); + } + +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname) + { + DSO_FUNC_TYPE ret = NULL; + + if((dso == NULL) || (symname == NULL)) + { + DSOerr(DSO_F_DSO_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER); return(NULL); } - if(dso->meth->dso_bind == NULL) + if(dso->meth->dso_bind_func == NULL) { - DSOerr(DSO_F_DSO_BIND,DSO_R_UNSUPPORTED); + DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_UNSUPPORTED); return(NULL); } - if(!dso->meth->dso_bind(dso, symname, &ret)) + if((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) { - DSOerr(DSO_F_DSO_BIND,DSO_R_SYM_FAILURE); + DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_SYM_FAILURE); return(NULL); } /* Success */ return(ret); } + +/* I don't really like these *_ctrl functions very much to be perfectly + * honest. For one thing, I think I have to return a negative value for + * any error because possible DSO_ctrl() commands may return values + * such as "size"s that can legitimately be zero (making the standard + * "if(DSO_cmd(...))" form that works almost everywhere else fail at + * odd times. I'd prefer "output" values to be passed by reference and + * the return value as success/failure like usual ... but we conform + * when we must... :-) */ +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return(-1); + } + /* We should intercept certain generic commands and only pass control + * to the method-specific ctrl() function if it's something we don't + * handle. */ + switch(cmd) + { + case DSO_CTRL_GET_FLAGS: + return dso->flags; + case DSO_CTRL_SET_FLAGS: + dso->flags = (int)larg; + return(0); + case DSO_CTRL_OR_FLAGS: + dso->flags |= (int)larg; + return(0); + default: + break; + } + if((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) + { + DSOerr(DSO_F_DSO_CTRL,DSO_R_UNSUPPORTED); + return(-1); + } + return(dso->meth->dso_ctrl(dso,cmd,larg,parg)); + } + +int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb, + DSO_NAME_CONVERTER_FUNC *oldcb) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_SET_NAME_CONVERTER, + ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if(oldcb) + *oldcb = dso->name_converter; + dso->name_converter = cb; + return(1); + } + +const char *DSO_get_filename(DSO *dso) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_GET_FILENAME,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + return(dso->filename); + } + +int DSO_set_filename(DSO *dso, const char *filename) + { + char *copied; + + if((dso == NULL) || (filename == NULL)) + { + DSOerr(DSO_F_DSO_SET_FILENAME,ERR_R_PASSED_NULL_PARAMETER); + return(0); + } + if(dso->loaded_filename) + { + DSOerr(DSO_F_DSO_SET_FILENAME,DSO_R_DSO_ALREADY_LOADED); + return(0); + } + /* We'll duplicate filename */ + copied = OPENSSL_malloc(strlen(filename) + 1); + if(copied == NULL) + { + DSOerr(DSO_F_DSO_SET_FILENAME,ERR_R_MALLOC_FAILURE); + return(0); + } + BUF_strlcpy(copied, filename, strlen(filename) + 1); + if(dso->filename) + OPENSSL_free(dso->filename); + dso->filename = copied; + return(1); + } + +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2) + { + char *result = NULL; + + if(dso == NULL || filespec1 == NULL) + { + DSOerr(DSO_F_DSO_MERGE,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) + { + if(dso->merger != NULL) + result = dso->merger(dso, filespec1, filespec2); + else if(dso->meth->dso_merger != NULL) + result = dso->meth->dso_merger(dso, + filespec1, filespec2); + } + return(result); + } + +char *DSO_convert_filename(DSO *dso, const char *filename) + { + char *result = NULL; + + if(dso == NULL) + { + DSOerr(DSO_F_DSO_CONVERT_FILENAME,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(filename == NULL) + filename = dso->filename; + if(filename == NULL) + { + DSOerr(DSO_F_DSO_CONVERT_FILENAME,DSO_R_NO_FILENAME); + return(NULL); + } + if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) + { + if(dso->name_converter != NULL) + result = dso->name_converter(dso, filename); + else if(dso->meth->dso_name_converter != NULL) + result = dso->meth->dso_name_converter(dso, filename); + } + if(result == NULL) + { + result = OPENSSL_malloc(strlen(filename) + 1); + if(result == NULL) + { + DSOerr(DSO_F_DSO_CONVERT_FILENAME, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + BUF_strlcpy(result, filename, strlen(filename) + 1); + } + return(result); + } + +const char *DSO_get_loaded_filename(DSO *dso) + { + if(dso == NULL) + { + DSOerr(DSO_F_DSO_GET_LOADED_FILENAME, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + return(dso->loaded_filename); + } + +int DSO_pathbyaddr(void *addr,char *path,int sz) + { + DSO_METHOD *meth = default_DSO_meth; + if (meth == NULL) meth = DSO_METHOD_openssl(); + if (meth->pathbyaddr == NULL) + { + DSOerr(DSO_F_DSO_PATHBYADDR,DSO_R_UNSUPPORTED); + return -1; + } + return (*meth->pathbyaddr)(addr,path,sz); + } + +void *DSO_global_lookup(const char *name) + { + DSO_METHOD *meth = default_DSO_meth; + if (meth == NULL) meth = DSO_METHOD_openssl(); + if (meth->globallookup == NULL) + { + DSOerr(DSO_F_DSO_GLOBAL_LOOKUP,DSO_R_UNSUPPORTED); + return NULL; + } + return (*meth->globallookup)(name); + }