aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2005-12-30 22:53:59 +0000
committerAndy Polyakov <appro@openssl.org>2005-12-30 22:53:59 +0000
commit68b64fb6102737bf84de9e25168abbf7e969b54b (patch)
treefbd215080bb8f241fead7db2d4524f923d146b07
parent34b537ee66eb7d327ff04121ccb7b9cc6b07ab3e (diff)
downloadopenssl-68b64fb6102737bf84de9e25168abbf7e969b54b.tar.gz
Add DSO_global_lookup_func implementation. See commentary in dso_lib.c
for further details.
-rw-r--r--crypto/dso/dso.h4
-rw-r--r--crypto/dso/dso_dl.c12
-rw-r--r--crypto/dso/dso_dlfcn.c18
-rw-r--r--crypto/dso/dso_err.c1
-rw-r--r--crypto/dso/dso_lib.c21
-rw-r--r--crypto/dso/dso_win32.c65
6 files changed, 118 insertions, 3 deletions
diff --git a/crypto/dso/dso.h b/crypto/dso/dso.h
index 5da0a55f2a..10efa4ac8d 100644
--- a/crypto/dso/dso.h
+++ b/crypto/dso/dso.h
@@ -173,6 +173,9 @@ typedef struct dso_meth_st
/* Return pathname of the module containing location */
int (*pathbyaddr)(void *addr,char *path,int sz);
+ /* Perform global symbol lookup, i.e. among *all* modules,
+ * see commentray in dso_lib.c for further details. */
+ DSO_FUNC_TYPE (*globallookup)(const char *symname);
} DSO_METHOD;
/**********************************************************************/
@@ -357,6 +360,7 @@ void ERR_load_DSO_strings(void);
#define DSO_F_WIN32_SPLITTER 136
#define DSO_F_WIN32_UNLOAD 121
#define DSO_F_PATHBYADDR 137
+#define DSO_F_GLOBAL_LOOKUP_FUNC 138
/* Reason codes. */
#define DSO_R_CTRL_FAILED 100
diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c
index dccb8e7ee8..7c123c8580 100644
--- a/crypto/dso/dso_dl.c
+++ b/crypto/dso/dso_dl.c
@@ -86,6 +86,7 @@ static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg);
static char *dl_name_converter(DSO *dso, const char *filename);
static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2);
static int dl_pathbyaddr(void *addr,char *path,int sz);
+static DSO_FUNC_TYPE dl_globallookup(const char *name);
static DSO_METHOD dso_meth_dl = {
"OpenSSL 'dl' shared library method",
@@ -103,7 +104,8 @@ static DSO_METHOD dso_meth_dl = {
dl_merger,
NULL, /* init */
NULL, /* finish */
- dl_pathbyaddr
+ dl_pathbyaddr,
+ dl_globallookup
};
DSO_METHOD *DSO_METHOD_dl(void)
@@ -380,4 +382,12 @@ static int dl_pathbyaddr(void *addr,char *path,int sz)
return -1;
}
+
+static DSO_FUNC_TYPE dl_globallookup(const char *name)
+ {
+ DSO_FUNC_TYPE ret;
+ shl_t h = NULL;
+
+ return shl_findsym(&h,name,TYPE_UNDEFINED,&ret) ? NULL : ret;
+ }
#endif /* DSO_DL */
diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c
index 6d6ee758ef..a4ab38f850 100644
--- a/crypto/dso/dso_dlfcn.c
+++ b/crypto/dso/dso_dlfcn.c
@@ -99,6 +99,7 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename);
static char *dlfcn_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int dlfcn_pathbyaddr(void *addr,char *path,int sz);
+static DSO_FUNC_TYPE dlfcn_globallookup(const char *name);
static DSO_METHOD dso_meth_dlfcn = {
"OpenSSL 'dlfcn' shared library method",
@@ -116,7 +117,8 @@ static DSO_METHOD dso_meth_dlfcn = {
dlfcn_merger,
NULL, /* init */
NULL, /* finish */
- dlfcn_pathbyaddr
+ dlfcn_pathbyaddr,
+ dlfcn_globallookup
};
DSO_METHOD *DSO_METHOD_dlfcn(void)
@@ -443,4 +445,18 @@ static int dlfcn_pathbyaddr(void *addr,char *path,int sz)
ERR_add_error_data(4, "dlfcn_pathbyaddr(): ", dlerror());
return -1;
}
+
+static DSO_FUNC_TYPE dlfcn_globallookup(const char *name)
+ {
+ union { void *p; DSO_FUNC_TYPE f; } ret = { NULL };
+ void *handle = dlopen(NULL,RTLD_LAZY);
+
+ if (handle)
+ {
+ ret.p = dlsym(handle,name);
+ dlclose(handle);
+ }
+
+ return ret.f;
+ }
#endif /* DSO_DLFCN */
diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c
index a88db0dd80..009a543445 100644
--- a/crypto/dso/dso_err.c
+++ b/crypto/dso/dso_err.c
@@ -108,6 +108,7 @@ static ERR_STRING_DATA DSO_str_functs[]=
{ERR_FUNC(DSO_F_WIN32_SPLITTER), "WIN32_SPLITTER"},
{ERR_FUNC(DSO_F_WIN32_UNLOAD), "WIN32_UNLOAD"},
{ERR_FUNC(DSO_F_PATHBYADDR), "DSO_pathbyaddr"},
+{ERR_FUNC(DSO_F_GLOBAL_LOOKUP_FUNC), "DSO_global_lookup_func"},
{0,NULL}
};
diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c
index 12ad097a28..8330c7d387 100644
--- a/crypto/dso/dso_lib.c
+++ b/crypto/dso/dso_lib.c
@@ -289,6 +289,7 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_UNSUPPORTED);
return(NULL);
}
+fprintf(stderr,"boo\n");
if((ret = dso->meth->dso_bind_func(dso, symname)) == NULL)
{
DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_SYM_FAILURE);
@@ -476,3 +477,23 @@ int DSO_pathbyaddr(void *addr,char *path,int sz)
}
return (*meth->pathbyaddr)(addr,path,sz);
}
+
+/* This function should be used with caution! It looks up symbols in
+ * *all* loaded modules and if module gets unloaded by somebody else
+ * attempt to dereference the pointer is doomed to have fatal
+ * consequences. Primary usage for this function is to probe *core*
+ * system functionality, e.g. check if getnameinfo(3) is available
+ * at run-time without bothering about OS-specific details such as
+ * libc.so.versioning or where does it actually reside: in libc
+ * itself or libsocket. */
+DSO_FUNC_TYPE DSO_global_lookup_func(const char *name)
+ {
+ DSO_METHOD *meth = default_DSO_meth;
+ if (meth == NULL) meth = DSO_METHOD_openssl();
+ if (meth->globallookup == NULL)
+ {
+ DSOerr(DSO_F_GLOBAL_LOOKUP_FUNC,DSO_R_UNSUPPORTED);
+ return NULL;
+ }
+ return (*meth->globallookup)(name);
+ }
diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c
index b44f25c579..73ffe36591 100644
--- a/crypto/dso/dso_win32.c
+++ b/crypto/dso/dso_win32.c
@@ -129,6 +129,7 @@ static char *win32_name_converter(DSO *dso, const char *filename);
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int win32_pathbyaddr(void *addr,char *path,int sz);
+static DSO_FUNC_TYPE win32_globallookup(const char *name);
static const char *openssl_strnchr(const char *string, int c, size_t len);
@@ -148,7 +149,8 @@ static DSO_METHOD dso_meth_win32 = {
win32_merger,
NULL, /* init */
NULL, /* finish */
- win32_pathbyaddr
+ win32_pathbyaddr,
+ win32_globallookup
};
DSO_METHOD *DSO_METHOD_win32(void)
@@ -770,4 +772,65 @@ static int win32_pathbyaddr(void *addr,char *path,int sz)
FreeLibrary(dll);
return 0;
}
+
+static DSO_FUNC_TYPE win32_globallookup(const char *name)
+ {
+ HMODULE dll;
+ HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
+ MODULEENTRY32 me32;
+ CREATETOOLHELP32SNAPSHOT create_snap;
+ CLOSETOOLHELP32SNAPSHOT close_snap;
+ MODULE32 module_first, module_next;
+ FARPROC ret=NULL;
+
+ dll = LoadLibrary(TEXT(DLLNAME));
+ if (dll == NULL)
+ {
+ DSOerr(DSO_F_GLOBAL_LOOKUP_FUNC,DSO_R_UNSUPPORTED);
+ return NULL;
+ }
+
+ create_snap = (CREATETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll,"CreateToolhelp32Snapshot");
+ if (create_snap == NULL)
+ {
+ FreeLibrary(dll);
+ DSOerr(DSO_F_GLOBAL_LOOKUP_FUNC,DSO_R_UNSUPPORTED);
+ return NULL;
+ }
+ /* We take the rest for granted... */
+#ifdef _WIN32_WCE
+ close_snap = (CLOSETOOLHELP32SNAPSHOT)
+ GetProcAddress(dll,"CloseToolhelp32Snapshot");
+#else
+ close_snap = (CLOSETOOLHELP32SNAPSHOT)CloseHandle;
+#endif
+ module_first = (MODULE32)GetProcAddress(dll,"Module32First");
+ module_next = (MODULE32)GetProcAddress(dll,"Module32Next");
+
+ hModuleSnap = (*create_snap)(TH32CS_SNAPMODULE,0);
+ if( hModuleSnap == INVALID_HANDLE_VALUE ) return NULL;
+
+ me32.dwSize = sizeof(me32);
+
+ if (!(*module_first)(hModuleSnap,&me32))
+ {
+ (*close_snap)(hModuleSnap);
+ FreeLibrary(dll);
+ return NULL;
+ }
+
+ do {
+ if (ret = GetProcAddress(me32.hModule,fname))
+ {
+ (*close_snap)(hModuleSnap);
+ FreeLibrary(dll);
+ return ret;
+ }
+ } while((*module_next)(hModuleSnap,&me32));
+
+ (*close_snap)(hModuleSnap);
+ FreeLibrary(dll);
+ return NULL;
+ }
#endif /* DSO_WIN32 */