diff options
Diffstat (limited to 'src/lib/libcrypto/dso/dso_dlfcn.c')
-rw-r--r-- | src/lib/libcrypto/dso/dso_dlfcn.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/src/lib/libcrypto/dso/dso_dlfcn.c b/src/lib/libcrypto/dso/dso_dlfcn.c index e709c721cc..1a19164d3b 100644 --- a/src/lib/libcrypto/dso/dso_dlfcn.c +++ b/src/lib/libcrypto/dso/dso_dlfcn.c | |||
@@ -74,7 +74,7 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) | |||
74 | /* Part of the hack in "dlfcn_load" ... */ | 74 | /* Part of the hack in "dlfcn_load" ... */ |
75 | #define DSO_MAX_TRANSLATED_SIZE 256 | 75 | #define DSO_MAX_TRANSLATED_SIZE 256 |
76 | 76 | ||
77 | static int dlfcn_load(DSO *dso, const char *filename); | 77 | static int dlfcn_load(DSO *dso); |
78 | static int dlfcn_unload(DSO *dso); | 78 | static int dlfcn_unload(DSO *dso); |
79 | static void *dlfcn_bind_var(DSO *dso, const char *symname); | 79 | static void *dlfcn_bind_var(DSO *dso, const char *symname); |
80 | static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); | 80 | static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); |
@@ -82,8 +82,9 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname); | |||
82 | static int dlfcn_unbind(DSO *dso, char *symname, void *symptr); | 82 | static int dlfcn_unbind(DSO *dso, char *symname, void *symptr); |
83 | static int dlfcn_init(DSO *dso); | 83 | static int dlfcn_init(DSO *dso); |
84 | static int dlfcn_finish(DSO *dso); | 84 | static int dlfcn_finish(DSO *dso); |
85 | #endif | ||
86 | static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); | 85 | static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); |
86 | #endif | ||
87 | static char *dlfcn_name_converter(DSO *dso, const char *filename); | ||
87 | 88 | ||
88 | static DSO_METHOD dso_meth_dlfcn = { | 89 | static DSO_METHOD dso_meth_dlfcn = { |
89 | "OpenSSL 'dlfcn' shared library method", | 90 | "OpenSSL 'dlfcn' shared library method", |
@@ -96,7 +97,8 @@ static DSO_METHOD dso_meth_dlfcn = { | |||
96 | NULL, /* unbind_var */ | 97 | NULL, /* unbind_var */ |
97 | NULL, /* unbind_func */ | 98 | NULL, /* unbind_func */ |
98 | #endif | 99 | #endif |
99 | dlfcn_ctrl, | 100 | NULL, /* ctrl */ |
101 | dlfcn_name_converter, | ||
100 | NULL, /* init */ | 102 | NULL, /* init */ |
101 | NULL /* finish */ | 103 | NULL /* finish */ |
102 | }; | 104 | }; |
@@ -130,41 +132,40 @@ DSO_METHOD *DSO_METHOD_dlfcn(void) | |||
130 | * (i) the handle (void*) returned from dlopen(). | 132 | * (i) the handle (void*) returned from dlopen(). |
131 | */ | 133 | */ |
132 | 134 | ||
133 | static int dlfcn_load(DSO *dso, const char *filename) | 135 | static int dlfcn_load(DSO *dso) |
134 | { | 136 | { |
135 | void *ptr; | 137 | void *ptr = NULL; |
136 | char translated[DSO_MAX_TRANSLATED_SIZE]; | 138 | /* See applicable comments in dso_dl.c */ |
137 | int len; | 139 | char *filename = DSO_convert_filename(dso, NULL); |
138 | 140 | ||
139 | /* NB: This is a hideous hack, but I'm not yet sure what | 141 | if(filename == NULL) |
140 | * to replace it with. This attempts to convert any filename, | ||
141 | * that looks like it has no path information, into a | ||
142 | * translated form, e. "blah" -> "libblah.so" */ | ||
143 | len = strlen(filename); | ||
144 | if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && | ||
145 | (len + 6 < DSO_MAX_TRANSLATED_SIZE) && | ||
146 | (strstr(filename, "/") == NULL)) | ||
147 | { | 142 | { |
148 | sprintf(translated, "lib%s.so", filename); | 143 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_NO_FILENAME); |
149 | ptr = dlopen(translated, DLOPEN_FLAG); | 144 | goto err; |
150 | } | ||
151 | else | ||
152 | { | ||
153 | ptr = dlopen(filename, DLOPEN_FLAG); | ||
154 | } | 145 | } |
146 | ptr = dlopen(filename, DLOPEN_FLAG); | ||
155 | if(ptr == NULL) | 147 | if(ptr == NULL) |
156 | { | 148 | { |
157 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); | 149 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_LOAD_FAILED); |
158 | return(0); | 150 | ERR_add_error_data(4, "filename(", filename, "): ", dlerror()); |
151 | goto err; | ||
159 | } | 152 | } |
160 | if(!sk_push(dso->meth_data, (char *)ptr)) | 153 | if(!sk_push(dso->meth_data, (char *)ptr)) |
161 | { | 154 | { |
162 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_STACK_ERROR); | 155 | DSOerr(DSO_F_DLFCN_LOAD,DSO_R_STACK_ERROR); |
163 | dlclose(ptr); | 156 | goto err; |
164 | return(0); | ||
165 | } | 157 | } |
158 | /* Success */ | ||
159 | dso->loaded_filename = filename; | ||
166 | return(1); | 160 | return(1); |
167 | } | 161 | err: |
162 | /* Cleanup! */ | ||
163 | if(filename != NULL) | ||
164 | OPENSSL_free(filename); | ||
165 | if(ptr != NULL) | ||
166 | dlclose(ptr); | ||
167 | return(0); | ||
168 | } | ||
168 | 169 | ||
169 | static int dlfcn_unload(DSO *dso) | 170 | static int dlfcn_unload(DSO *dso) |
170 | { | 171 | { |
@@ -214,6 +215,7 @@ static void *dlfcn_bind_var(DSO *dso, const char *symname) | |||
214 | if(sym == NULL) | 215 | if(sym == NULL) |
215 | { | 216 | { |
216 | DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_SYM_FAILURE); | 217 | DSOerr(DSO_F_DLFCN_BIND_VAR,DSO_R_SYM_FAILURE); |
218 | ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); | ||
217 | return(NULL); | 219 | return(NULL); |
218 | } | 220 | } |
219 | return(sym); | 221 | return(sym); |
@@ -244,33 +246,44 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) | |||
244 | if(sym == NULL) | 246 | if(sym == NULL) |
245 | { | 247 | { |
246 | DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); | 248 | DSOerr(DSO_F_DLFCN_BIND_FUNC,DSO_R_SYM_FAILURE); |
249 | ERR_add_error_data(4, "symname(", symname, "): ", dlerror()); | ||
247 | return(NULL); | 250 | return(NULL); |
248 | } | 251 | } |
249 | return(sym); | 252 | return(sym); |
250 | } | 253 | } |
251 | 254 | ||
252 | static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg) | 255 | static char *dlfcn_name_converter(DSO *dso, const char *filename) |
253 | { | 256 | { |
254 | if(dso == NULL) | 257 | char *translated; |
258 | int len, rsize, transform; | ||
259 | |||
260 | len = strlen(filename); | ||
261 | rsize = len + 1; | ||
262 | transform = (strstr(filename, "/") == NULL); | ||
263 | if(transform) | ||
255 | { | 264 | { |
256 | DSOerr(DSO_F_DLFCN_CTRL,ERR_R_PASSED_NULL_PARAMETER); | 265 | /* We will convert this to "%s.so" or "lib%s.so" */ |
257 | return(-1); | 266 | rsize += 3; /* The length of ".so" */ |
267 | if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) | ||
268 | rsize += 3; /* The length of "lib" */ | ||
258 | } | 269 | } |
259 | switch(cmd) | 270 | translated = OPENSSL_malloc(rsize); |
271 | if(translated == NULL) | ||
260 | { | 272 | { |
261 | case DSO_CTRL_GET_FLAGS: | 273 | DSOerr(DSO_F_DLFCN_NAME_CONVERTER, |
262 | return dso->flags; | 274 | DSO_R_NAME_TRANSLATION_FAILED); |
263 | case DSO_CTRL_SET_FLAGS: | 275 | return(NULL); |
264 | dso->flags = (int)larg; | ||
265 | return(0); | ||
266 | case DSO_CTRL_OR_FLAGS: | ||
267 | dso->flags |= (int)larg; | ||
268 | return(0); | ||
269 | default: | ||
270 | break; | ||
271 | } | 276 | } |
272 | DSOerr(DSO_F_DLFCN_CTRL,DSO_R_UNKNOWN_COMMAND); | 277 | if(transform) |
273 | return(-1); | 278 | { |
279 | if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) | ||
280 | sprintf(translated, "lib%s.so", filename); | ||
281 | else | ||
282 | sprintf(translated, "%s.so", filename); | ||
283 | } | ||
284 | else | ||
285 | sprintf(translated, "%s", filename); | ||
286 | return(translated); | ||
274 | } | 287 | } |
275 | 288 | ||
276 | #endif /* DSO_DLFCN */ | 289 | #endif /* DSO_DLFCN */ |