diff options
Diffstat (limited to 'src/lib/libcrypto/dso/dso_dl.c')
-rw-r--r-- | src/lib/libcrypto/dso/dso_dl.c | 112 |
1 files changed, 70 insertions, 42 deletions
diff --git a/src/lib/libcrypto/dso/dso_dl.c b/src/lib/libcrypto/dso/dso_dl.c index 455bd66ecf..195717e993 100644 --- a/src/lib/libcrypto/dso/dso_dl.c +++ b/src/lib/libcrypto/dso/dso_dl.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* dso_dl.c */ | 1 | /* dso_dl.c */ |
2 | /* Written by Richard Levitte (levitte@openssl.org) for the OpenSSL | 2 | /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL |
3 | * project 2000. | 3 | * project 2000. |
4 | */ | 4 | */ |
5 | /* ==================================================================== | 5 | /* ==================================================================== |
@@ -72,7 +72,7 @@ DSO_METHOD *DSO_METHOD_dl(void) | |||
72 | /* Part of the hack in "dl_load" ... */ | 72 | /* Part of the hack in "dl_load" ... */ |
73 | #define DSO_MAX_TRANSLATED_SIZE 256 | 73 | #define DSO_MAX_TRANSLATED_SIZE 256 |
74 | 74 | ||
75 | static int dl_load(DSO *dso, const char *filename); | 75 | static int dl_load(DSO *dso); |
76 | static int dl_unload(DSO *dso); | 76 | static int dl_unload(DSO *dso); |
77 | static void *dl_bind_var(DSO *dso, const char *symname); | 77 | static void *dl_bind_var(DSO *dso, const char *symname); |
78 | static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname); | 78 | static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname); |
@@ -81,8 +81,9 @@ static int dl_unbind_var(DSO *dso, char *symname, void *symptr); | |||
81 | static int dl_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr); | 81 | static int dl_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr); |
82 | static int dl_init(DSO *dso); | 82 | static int dl_init(DSO *dso); |
83 | static int dl_finish(DSO *dso); | 83 | static int dl_finish(DSO *dso); |
84 | static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg); | ||
84 | #endif | 85 | #endif |
85 | static long dl_ctrl(DSO *dso, int cmd, long larg, void *parg); | 86 | static char *dl_name_converter(DSO *dso, const char *filename); |
86 | 87 | ||
87 | static DSO_METHOD dso_meth_dl = { | 88 | static DSO_METHOD dso_meth_dl = { |
88 | "OpenSSL 'dl' shared library method", | 89 | "OpenSSL 'dl' shared library method", |
@@ -95,7 +96,8 @@ static DSO_METHOD dso_meth_dl = { | |||
95 | NULL, /* unbind_var */ | 96 | NULL, /* unbind_var */ |
96 | NULL, /* unbind_func */ | 97 | NULL, /* unbind_func */ |
97 | #endif | 98 | #endif |
98 | dl_ctrl, | 99 | NULL, /* ctrl */ |
100 | dl_name_converter, | ||
99 | NULL, /* init */ | 101 | NULL, /* init */ |
100 | NULL /* finish */ | 102 | NULL /* finish */ |
101 | }; | 103 | }; |
@@ -111,40 +113,43 @@ DSO_METHOD *DSO_METHOD_dl(void) | |||
111 | * type so the cast is safe. | 113 | * type so the cast is safe. |
112 | */ | 114 | */ |
113 | 115 | ||
114 | #if defined(__hpux) | 116 | static int dl_load(DSO *dso) |
115 | static const char extension[] = ".sl"; | ||
116 | #else | ||
117 | static const char extension[] = ".so"; | ||
118 | #endif | ||
119 | static int dl_load(DSO *dso, const char *filename) | ||
120 | { | 117 | { |
121 | shl_t ptr; | 118 | shl_t ptr = NULL; |
122 | char translated[DSO_MAX_TRANSLATED_SIZE]; | 119 | /* We don't do any fancy retries or anything, just take the method's |
123 | int len; | 120 | * (or DSO's if it has the callback set) best translation of the |
121 | * platform-independant filename and try once with that. */ | ||
122 | char *filename= DSO_convert_filename(dso, NULL); | ||
124 | 123 | ||
125 | /* The same comment as in dlfcn_load applies here. bleurgh. */ | 124 | if(filename == NULL) |
126 | len = strlen(filename) + strlen(extension); | ||
127 | if((dso->flags & DSO_FLAG_NAME_TRANSLATION) && | ||
128 | (len + 3 < DSO_MAX_TRANSLATED_SIZE) && | ||
129 | (strstr(filename, "/") == NULL)) | ||
130 | { | 125 | { |
131 | sprintf(translated, "lib%s%s", filename, extension); | 126 | DSOerr(DSO_F_DL_LOAD,DSO_R_NO_FILENAME); |
132 | ptr = shl_load(translated, BIND_IMMEDIATE, NULL); | 127 | goto err; |
133 | } | 128 | } |
134 | else | 129 | ptr = shl_load(filename, BIND_IMMEDIATE|DYNAMIC_PATH, NULL); |
135 | ptr = shl_load(filename, BIND_IMMEDIATE, NULL); | ||
136 | if(ptr == NULL) | 130 | if(ptr == NULL) |
137 | { | 131 | { |
138 | DSOerr(DSO_F_DL_LOAD,DSO_R_LOAD_FAILED); | 132 | DSOerr(DSO_F_DL_LOAD,DSO_R_LOAD_FAILED); |
139 | return(0); | 133 | ERR_add_error_data(4, "filename(", filename, "): ", |
134 | strerror(errno)); | ||
135 | goto err; | ||
140 | } | 136 | } |
141 | if(!sk_push(dso->meth_data, (char *)ptr)) | 137 | if(!sk_push(dso->meth_data, (char *)ptr)) |
142 | { | 138 | { |
143 | DSOerr(DSO_F_DL_LOAD,DSO_R_STACK_ERROR); | 139 | DSOerr(DSO_F_DL_LOAD,DSO_R_STACK_ERROR); |
144 | shl_unload(ptr); | 140 | goto err; |
145 | return(0); | ||
146 | } | 141 | } |
142 | /* Success, stick the converted filename we've loaded under into the DSO | ||
143 | * (it also serves as the indicator that we are currently loaded). */ | ||
144 | dso->loaded_filename = filename; | ||
147 | return(1); | 145 | return(1); |
146 | err: | ||
147 | /* Cleanup! */ | ||
148 | if(filename != NULL) | ||
149 | OPENSSL_free(filename); | ||
150 | if(ptr != NULL) | ||
151 | shl_unload(ptr); | ||
152 | return(0); | ||
148 | } | 153 | } |
149 | 154 | ||
150 | static int dl_unload(DSO *dso) | 155 | static int dl_unload(DSO *dso) |
@@ -195,6 +200,8 @@ static void *dl_bind_var(DSO *dso, const char *symname) | |||
195 | if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) | 200 | if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) |
196 | { | 201 | { |
197 | DSOerr(DSO_F_DL_BIND_VAR,DSO_R_SYM_FAILURE); | 202 | DSOerr(DSO_F_DL_BIND_VAR,DSO_R_SYM_FAILURE); |
203 | ERR_add_error_data(4, "symname(", symname, "): ", | ||
204 | strerror(errno)); | ||
198 | return(NULL); | 205 | return(NULL); |
199 | } | 206 | } |
200 | return(sym); | 207 | return(sym); |
@@ -224,33 +231,54 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname) | |||
224 | if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) | 231 | if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) |
225 | { | 232 | { |
226 | DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_SYM_FAILURE); | 233 | DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_SYM_FAILURE); |
234 | ERR_add_error_data(4, "symname(", symname, "): ", | ||
235 | strerror(errno)); | ||
227 | return(NULL); | 236 | return(NULL); |
228 | } | 237 | } |
229 | return((DSO_FUNC_TYPE)sym); | 238 | return((DSO_FUNC_TYPE)sym); |
230 | } | 239 | } |
231 | 240 | ||
232 | static long dl_ctrl(DSO *dso, int cmd, long larg, void *parg) | 241 | /* This function is identical to the one in dso_dlfcn.c, but as it is highly |
242 | * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at the | ||
243 | * same time, there's no great duplicating the code. Figuring out an elegant | ||
244 | * way to share one copy of the code would be more difficult and would not | ||
245 | * leave the implementations independant. */ | ||
246 | #if defined(__hpux) | ||
247 | static const char extension[] = ".sl"; | ||
248 | #else | ||
249 | static const char extension[] = ".so"; | ||
250 | #endif | ||
251 | static char *dl_name_converter(DSO *dso, const char *filename) | ||
233 | { | 252 | { |
234 | if(dso == NULL) | 253 | char *translated; |
254 | int len, rsize, transform; | ||
255 | |||
256 | len = strlen(filename); | ||
257 | rsize = len + 1; | ||
258 | transform = (strstr(filename, "/") == NULL); | ||
235 | { | 259 | { |
236 | DSOerr(DSO_F_DL_CTRL,ERR_R_PASSED_NULL_PARAMETER); | 260 | /* We will convert this to "%s.s?" or "lib%s.s?" */ |
237 | return(-1); | 261 | rsize += strlen(extension);/* The length of ".s?" */ |
262 | if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) | ||
263 | rsize += 3; /* The length of "lib" */ | ||
238 | } | 264 | } |
239 | switch(cmd) | 265 | translated = OPENSSL_malloc(rsize); |
266 | if(translated == NULL) | ||
240 | { | 267 | { |
241 | case DSO_CTRL_GET_FLAGS: | 268 | DSOerr(DSO_F_DL_NAME_CONVERTER, |
242 | return dso->flags; | 269 | DSO_R_NAME_TRANSLATION_FAILED); |
243 | case DSO_CTRL_SET_FLAGS: | 270 | return(NULL); |
244 | dso->flags = larg; | ||
245 | return(0); | ||
246 | case DSO_CTRL_OR_FLAGS: | ||
247 | dso->flags |= larg; | ||
248 | return(0); | ||
249 | default: | ||
250 | break; | ||
251 | } | 271 | } |
252 | DSOerr(DSO_F_DL_CTRL,DSO_R_UNKNOWN_COMMAND); | 272 | if(transform) |
253 | return(-1); | 273 | { |
274 | if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) | ||
275 | sprintf(translated, "lib%s%s", filename, extension); | ||
276 | else | ||
277 | sprintf(translated, "%s%s", filename, extension); | ||
278 | } | ||
279 | else | ||
280 | sprintf(translated, "%s", filename); | ||
281 | return(translated); | ||
254 | } | 282 | } |
255 | 283 | ||
256 | #endif /* DSO_DL */ | 284 | #endif /* DSO_DL */ |