aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES7
-rw-r--r--crypto/dso/dso.h54
-rw-r--r--crypto/dso/dso_dl.c44
-rw-r--r--crypto/dso/dso_dlfcn.c48
-rw-r--r--crypto/dso/dso_err.c24
-rw-r--r--crypto/dso/dso_lib.c34
-rw-r--r--crypto/dso/dso_null.c1
-rw-r--r--crypto/dso/dso_win32.c51
8 files changed, 235 insertions, 28 deletions
diff --git a/CHANGES b/CHANGES
index 4688929252..03b1f0059e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,13 @@
Changes between 0.9.5a and 0.9.6 [xx XXX 2000]
+ *) Added native name translation to the existing DSO code
+ that will convert (if the flag to do so is set) filenames
+ that are sufficiently small and have no path information
+ into a canonical native form. Eg. "blah" converted to
+ "libblah.so" or "blah.dll" etc.
+ [Geoff Thorpe]
+
*) New function ERR_error_string_n(e, buf, len) which is like
ERR_error_string(e, buf), but writes at most 'len' bytes
including the 0 terminator. For ERR_error_string_n, 'buf'
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 */