diff options
Diffstat (limited to 'crypto/dso')
-rw-r--r-- | crypto/dso/dso.h | 54 | ||||
-rw-r--r-- | crypto/dso/dso_dl.c | 44 | ||||
-rw-r--r-- | crypto/dso/dso_dlfcn.c | 48 | ||||
-rw-r--r-- | crypto/dso/dso_err.c | 24 | ||||
-rw-r--r-- | crypto/dso/dso_lib.c | 34 | ||||
-rw-r--r-- | crypto/dso/dso_null.c | 1 | ||||
-rw-r--r-- | crypto/dso/dso_win32.c | 51 |
7 files changed, 228 insertions, 28 deletions
diff --git a/crypto/dso/dso.h b/crypto/dso/dso.h index 91a44805e3..281af47c26 100644 --- a/crypto/dso/dso.h +++ b/crypto/dso/dso.h @@ -65,6 +65,20 @@ extern "C" { #endif +/* These values are used as commands to DSO_ctrl() */ +#define DSO_CTRL_GET_FLAGS 1 +#define DSO_CTRL_SET_FLAGS 2 +#define DSO_CTRL_OR_FLAGS 3 + +/* These flags control the translation of file-names from canonical to + * native. Eg. in the CryptoSwift support, the "dl" and "dlfcn" + * methods will translate "swift" -> "libswift.so" whereas the "win32" + * method will translate "swift" -> "swift.dll". NB: Until I can figure + * out how to be more "conventional" with this, the methods will only + * honour this flag if it looks like it was passed a file without any + * path and if the filename is small enough. + */ +#define DSO_FLAG_NAME_TRANSLATION 0x01 typedef struct dso_st DSO; @@ -83,7 +97,11 @@ typedef struct dso_meth_st /* Unbinds a symbol */ int (*dso_unbind)(DSO *dso, char *symname, void *symptr); #endif + /* The generic (yuck) "ctrl()" function. NB: Negative return + * values (rather than zero) indicate errors. */ + long (*dso_ctrl)(DSO *dso, int cmd, long larg, void *parg); + /* [De]Initialisation handlers. */ int (*init)(DSO *dso); int (*finish)(DSO *dso); } DSO_METHOD; @@ -113,6 +131,7 @@ DSO * DSO_new_method(DSO_METHOD *method); int DSO_free(DSO *dso); int DSO_flags(DSO *dso); int DSO_up(DSO *dso); +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg); void DSO_set_default_method(DSO_METHOD *meth); DSO_METHOD *DSO_get_default_method(void); @@ -121,8 +140,11 @@ DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth); /* The all-singing all-dancing load function, you normally pass NULL * for the first and third parameters. Use DSO_up and DSO_free for - * reference count handling. */ -DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth); + * subsequent reference count handling. Any flags passed in will be set + * in the constructed DSO after its init() function but before the + * load operation. This will be done with; + * DSO_ctrl(dso, DSO_CTRL_SET_FLAGS, flags, NULL); */ +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags); /* This function binds to a function, variable, whatever inside a * shared library. */ @@ -163,17 +185,21 @@ void ERR_load_DSO_strings(void); #define DSO_F_DLFCN_BIND 100 #define DSO_F_DLFCN_LOAD 101 #define DSO_F_DLFCN_UNLOAD 102 -#define DSO_F_DL_BIND 103 -#define DSO_F_DL_LOAD 104 -#define DSO_F_DL_UNLOAD 105 -#define DSO_F_DSO_BIND 106 -#define DSO_F_DSO_FREE 107 -#define DSO_F_DSO_LOAD 108 -#define DSO_F_DSO_NEW_METHOD 109 -#define DSO_F_DSO_UP 110 -#define DSO_F_WIN32_BIND 111 -#define DSO_F_WIN32_LOAD 112 -#define DSO_F_WIN32_UNLOAD 113 +#define DSO_F_DLFCN_CTRL 103 +#define DSO_F_DL_BIND 104 +#define DSO_F_DL_LOAD 105 +#define DSO_F_DL_UNLOAD 106 +#define DSO_F_DL_CTRL 107 +#define DSO_F_DSO_BIND 108 +#define DSO_F_DSO_FREE 109 +#define DSO_F_DSO_LOAD 110 +#define DSO_F_DSO_NEW_METHOD 111 +#define DSO_F_DSO_UP 112 +#define DSO_F_DSO_CTRL 113 +#define DSO_F_WIN32_BIND 114 +#define DSO_F_WIN32_LOAD 115 +#define DSO_F_WIN32_UNLOAD 116 +#define DSO_F_WIN32_CTRL 117 /* Reason codes. */ #define DSO_R_FINISH_FAILED 100 @@ -183,6 +209,8 @@ void ERR_load_DSO_strings(void); #define DSO_R_SYM_FAILURE 104 #define DSO_R_UNLOAD_FAILED 105 #define DSO_R_UNSUPPORTED 106 +#define DSO_R_UNKNOWN_COMMAND 107 +#define DSO_R_CTRL_FAILED 108 #ifdef __cplusplus } diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index e6e508d434..a4152e7723 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -69,6 +69,9 @@ DSO_METHOD *DSO_METHOD_dl(void) #include <dl.h> +/* Part of the hack in "dl_load" ... */ +#define DSO_MAX_TRANSLATED_SIZE 256 + static int dl_load(DSO *dso, const char *filename); static int dl_unload(DSO *dso); static int dl_bind(DSO *dso, const char *symname, void **symptr); @@ -77,6 +80,7 @@ static int dl_unbind(DSO *dso, char *symname, void *symptr); static int dl_init(DSO *dso); static int dl_finish(DSO *dso); #endif +static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg); static DSO_METHOD dso_meth_dl = { "OpenSSL 'dl' shared library method", @@ -87,6 +91,7 @@ static DSO_METHOD dso_meth_dl = { #if 0 NULL, /* unbind */ #endif + dl_ctrl, NULL, /* init */ NULL /* finish */ }; @@ -105,8 +110,20 @@ DSO_METHOD *DSO_METHOD_dl(void) static int dl_load(DSO *dso, const char *filename) { shl_t ptr; + char translated[DSO_MAX_TRANSLATED_SIZE]; + int len; - ptr = shl_load(filename, BIND_IMMEDIATE, NULL); + /* The same comment as in dlfcn_load applies here. bleurgh. */ + len = strlen(filename); + if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && + (len + 6 < DSO_MAX_TRANSLATED_SIZE) && + (strstr(filename, "/") == NULL)) + { + sprintf(translated, "lib%s.so", filename); + ptr = shl_load(translated, BIND_IMMEDIATE, NULL); + } + else + ptr = shl_load(filename, BIND_IMMEDIATE, NULL); if(ptr == NULL) { DSOerr(DSO_F_DL_LOAD,DSO_R_LOAD_FAILED); @@ -163,7 +180,6 @@ static int dl_bind(DSO *dso, const char *symname, void **symptr) DSOerr(DSO_F_DL_BIND,DSO_R_STACK_ERROR); return(0); } - /* Is this actually legal? */ ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); if(ptr == NULL) { @@ -179,4 +195,28 @@ static int dl_bind(DSO *dso, const char *symname, void **symptr) return(1); } +static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg) + { + if(dso == NULL) + { + DSOerr(DSO_F_DL_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return(-1); + } + 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; + } + DSOerr(DSO_F_DL_CTRL,DSO_R_UNKNOWN_COMMAND); + return(-1); + } + #endif /* DSO_DL */ diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index c5db28f356..cad1aedd4e 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -71,6 +71,9 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) #include <dlfcn.h> #endif +/* Part of the hack in "dlfcn_load" ... */ +#define DSO_MAX_TRANSLATED_SIZE 256 + static int dlfcn_load(DSO *dso, const char *filename); static int dlfcn_unload(DSO *dso); static int dlfcn_bind(DSO *dso, const char *symname, void **symptr); @@ -79,6 +82,7 @@ static int dlfcn_unbind(DSO *dso, char *symname, void *symptr); static int dlfcn_init(DSO *dso); static int dlfcn_finish(DSO *dso); #endif +static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); static DSO_METHOD dso_meth_dlfcn = { "OpenSSL 'dlfcn' shared library method", @@ -89,6 +93,7 @@ static DSO_METHOD dso_meth_dlfcn = { #if 0 NULL, /* unbind */ #endif + dlfcn_ctrl, NULL, /* init */ NULL /* finish */ }; @@ -105,8 +110,25 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) static int dlfcn_load(DSO *dso, const char *filename) { void *ptr; + char translated[DSO_MAX_TRANSLATED_SIZE]; + int len; - ptr = dlopen(filename, RTLD_NOW); + /* NB: This is a hideous hack, but I'm not yet sure what + * to replace it with. This attempts to convert any filename, + * that looks like it has no path information, into a + * translated form, e. "blah" -> "libblah.so" */ + len = strlen(filename); + if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && + (len + 6 < DSO_MAX_TRANSLATED_SIZE) && + (strstr(filename, "/") == NULL)) + { + sprintf(translated, "lib%s.so", filename); + ptr = dlopen(translated, RTLD_NOW); + } + else + { + ptr = dlopen(filename, RTLD_NOW); + } if(ptr == NULL) { DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); @@ -178,4 +200,28 @@ static int dlfcn_bind(DSO *dso, const char *symname, void **symptr) return(1); } +static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg) + { + if(dso == NULL) + { + DSOerr(DSO_F_DLFCN_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return(-1); + } + 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; + } + DSOerr(DSO_F_DLFCN_CTRL,DSO_R_UNKNOWN_COMMAND); + return(-1); + } + #endif /* DSO_DLFCN */ diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c index efe3226041..5d2457a9ff 100644 --- a/crypto/dso/dso_err.c +++ b/crypto/dso/dso_err.c @@ -66,20 +66,24 @@ #ifndef NO_ERR static ERR_STRING_DATA DSO_str_functs[]= { -{ERR_PACK(0,DSO_F_DLFCN_BIND,0), "DLFCN_BIND"}, -{ERR_PACK(0,DSO_F_DLFCN_LOAD,0), "DLFCN_LOAD"}, -{ERR_PACK(0,DSO_F_DLFCN_UNLOAD,0), "DLFCN_UNLOAD"}, -{ERR_PACK(0,DSO_F_DL_BIND,0), "DL_BIND"}, -{ERR_PACK(0,DSO_F_DL_LOAD,0), "DL_LOAD"}, -{ERR_PACK(0,DSO_F_DL_UNLOAD,0), "DL_UNLOAD"}, +{ERR_PACK(0,DSO_F_DLFCN_BIND,0), "dlfcn_bind"}, +{ERR_PACK(0,DSO_F_DLFCN_LOAD,0), "dlfcn_load"}, +{ERR_PACK(0,DSO_F_DLFCN_UNLOAD,0), "dlfcn_unload"}, +{ERR_PACK(0,DSO_F_DLFCN_CTRL,0), "dlfcn_ctrl"}, +{ERR_PACK(0,DSO_F_DL_BIND,0), "dl_bind"}, +{ERR_PACK(0,DSO_F_DL_LOAD,0), "dl_load"}, +{ERR_PACK(0,DSO_F_DL_UNLOAD,0), "dl_unload"}, +{ERR_PACK(0,DSO_F_DL_CTRL,0), "dl_ctrl"}, {ERR_PACK(0,DSO_F_DSO_BIND,0), "DSO_bind"}, {ERR_PACK(0,DSO_F_DSO_FREE,0), "DSO_free"}, {ERR_PACK(0,DSO_F_DSO_LOAD,0), "DSO_load"}, {ERR_PACK(0,DSO_F_DSO_NEW_METHOD,0), "DSO_new_method"}, {ERR_PACK(0,DSO_F_DSO_UP,0), "DSO_up"}, -{ERR_PACK(0,DSO_F_WIN32_BIND,0), "WIN32_BIND"}, -{ERR_PACK(0,DSO_F_WIN32_LOAD,0), "WIN32_LOAD"}, -{ERR_PACK(0,DSO_F_WIN32_UNLOAD,0), "WIN32_UNLOAD"}, +{ERR_PACK(0,DSO_F_DSO_CTRL,0), "DSO_ctrl"}, +{ERR_PACK(0,DSO_F_WIN32_BIND,0), "win32_bind"}, +{ERR_PACK(0,DSO_F_WIN32_LOAD,0), "win32_load"}, +{ERR_PACK(0,DSO_F_WIN32_UNLOAD,0), "win32_unload"}, +{ERR_PACK(0,DSO_F_WIN32_CTRL,0), "win32_ctrl"}, {0,NULL} }; @@ -92,6 +96,8 @@ static ERR_STRING_DATA DSO_str_reasons[]= {DSO_R_SYM_FAILURE ,"could not bind to the requested symbol name"}, {DSO_R_UNLOAD_FAILED ,"could not unload the shared library"}, {DSO_R_UNSUPPORTED ,"functionality not supported"}, +{DSO_R_UNKNOWN_COMMAND ,"unknown control command"}, +{DSO_R_CTRL_FAILED ,"control command failed"}, {0,NULL} }; diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 9430d0d76f..f41ebf1aa4 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -187,7 +187,7 @@ 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; @@ -209,6 +209,15 @@ DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth) } else ret = dso; + /* Bleurgh ... have to check for negative return values for + * errors. <grimace> */ + if(DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) + { + DSOerr(DSO_F_DSO_LOAD,DSO_R_CTRL_FAILED); + if(allocated) + DSO_free(ret); + return(NULL); + } if(ret->meth->dso_load == NULL) { DSOerr(DSO_F_DSO_LOAD,DSO_R_UNSUPPORTED); @@ -249,3 +258,26 @@ void *DSO_bind(DSO *dso, const char *symname) /* 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); + } + 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)); + } diff --git a/crypto/dso/dso_null.c b/crypto/dso/dso_null.c index ee6a31e32d..79e6eddca2 100644 --- a/crypto/dso/dso_null.c +++ b/crypto/dso/dso_null.c @@ -72,6 +72,7 @@ static DSO_METHOD dso_meth_null = { #if 0 NULL, /* unbind */ #endif + NULL, /* ctrl */ NULL, /* init */ NULL /* finish */ }; diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c index 296e10ff6f..edf5d75b0f 100644 --- a/crypto/dso/dso_win32.c +++ b/crypto/dso/dso_win32.c @@ -67,6 +67,9 @@ DSO_METHOD *DSO_METHOD_win32(void) } #else +/* Part of the hack in "win32_load" ... */ +#define DSO_MAX_TRANSLATED_SIZE 256 + static int win32_load(DSO *dso, const char *filename); static int win32_unload(DSO *dso); static int win32_bind(DSO *dso, const char *symname, void **symptr); @@ -75,6 +78,7 @@ static int win32_unbind(DSO *dso, char *symname, void *symptr); static int win32_init(DSO *dso); static int win32_finish(DSO *dso); #endif +static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg); static DSO_METHOD dso_meth_win32 = { "OpenSSL 'win32' shared library method", @@ -85,6 +89,7 @@ static DSO_METHOD dso_meth_win32 = { #if 0 NULL, /* unbind */ #endif + win32_ctrl, NULL, /* init */ NULL /* finish */ }; @@ -96,14 +101,32 @@ DSO_METHOD *DSO_METHOD_win32(void) /* For this DSO_METHOD, our meth_data STACK will contain; * (i) a pointer to the handle (HINSTANCE) returned from - * LoadLibrary(), and copied. + * LoadLibrary(), and copied. */ static int win32_load(DSO *dso, const char *filename) { HINSTANCE h, *p; + char translated[DSO_MAX_TRANSLATED_SIZE]; + int len; - h = LoadLibrary(filename); + /* NB: This is a hideous hack, but I'm not yet sure what + * to replace it with. This attempts to convert any filename, + * that looks like it has no path information, into a + * translated form, e. "blah" -> "blah.dll" ... I'm more + * comfortable putting hacks into win32 code though ;-) */ + len = strlen(filename); + if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && + (len + 4 < DSO_MAX_TRANSLATED_SIZE) && + (strstr(filename, "/") == NULL) + (strstr(filename, "\\") == NULL) + (strstr(filename, ":") == NULL)) + { + sprintf(translated, "%s.dll", filename); + h = LoadLibrary(translated); + } + else + h = LoadLibrary(filename); if(h == NULL) { DSOerr(DSO_F_WIN32_LOAD,DSO_R_LOAD_FAILED); @@ -190,4 +213,28 @@ static int win32_bind(DSO *dso, const char *symname, void **symptr) return(1); } +static int win32_ctrl(DSO *dso, int cmd, long larg, void *parg) + { + if(dso == NULL) + { + DSOerr(DSO_F_WIN32_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return(-1); + } + 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; + } + DSOerr(DSO_F_WIN32_CTRL,DSO_R_UNKNOWN_COMMAND); + return(-1); + } + #endif /* WIN32 */ |