OLD | NEW |
| (Empty) |
1 /* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */ | |
2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL | |
3 * project 2000. | |
4 */ | |
5 /* ==================================================================== | |
6 * Copyright (c) 2000 The OpenSSL Project. All rights reserved. | |
7 * | |
8 * Redistribution and use in source and binary forms, with or without | |
9 * modification, are permitted provided that the following conditions | |
10 * are met: | |
11 * | |
12 * 1. Redistributions of source code must retain the above copyright | |
13 * notice, this list of conditions and the following disclaimer. | |
14 * | |
15 * 2. Redistributions in binary form must reproduce the above copyright | |
16 * notice, this list of conditions and the following disclaimer in | |
17 * the documentation and/or other materials provided with the | |
18 * distribution. | |
19 * | |
20 * 3. All advertising materials mentioning features or use of this | |
21 * software must display the following acknowledgment: | |
22 * "This product includes software developed by the OpenSSL Project | |
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 * | |
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 * endorse or promote products derived from this software without | |
27 * prior written permission. For written permission, please contact | |
28 * licensing@OpenSSL.org. | |
29 * | |
30 * 5. Products derived from this software may not be called "OpenSSL" | |
31 * nor may "OpenSSL" appear in their names without prior written | |
32 * permission of the OpenSSL Project. | |
33 * | |
34 * 6. Redistributions of any form whatsoever must retain the following | |
35 * acknowledgment: | |
36 * "This product includes software developed by the OpenSSL Project | |
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 * | |
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 * ==================================================================== | |
52 * | |
53 * This product includes cryptographic software written by Eric Young | |
54 * (eay@cryptsoft.com). This product includes software written by Tim | |
55 * Hudson (tjh@cryptsoft.com). | |
56 * | |
57 */ | |
58 | |
59 #include <stdio.h> | |
60 #include "cryptlib.h" | |
61 #include <openssl/dso.h> | |
62 | |
63 #ifndef DSO_DL | |
64 DSO_METHOD *DSO_METHOD_dl(void) | |
65 { | |
66 return NULL; | |
67 } | |
68 #else | |
69 | |
70 #include <dl.h> | |
71 | |
72 /* Part of the hack in "dl_load" ... */ | |
73 #define DSO_MAX_TRANSLATED_SIZE 256 | |
74 | |
75 static int dl_load(DSO *dso); | |
76 static int dl_unload(DSO *dso); | |
77 static void *dl_bind_var(DSO *dso, const char *symname); | |
78 static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname); | |
79 #if 0 | |
80 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); | |
82 static int dl_init(DSO *dso); | |
83 static int dl_finish(DSO *dso); | |
84 static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg); | |
85 #endif | |
86 static char *dl_name_converter(DSO *dso, const char *filename); | |
87 static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2); | |
88 static int dl_pathbyaddr(void *addr,char *path,int sz); | |
89 static void *dl_globallookup(const char *name); | |
90 | |
91 static DSO_METHOD dso_meth_dl = { | |
92 "OpenSSL 'dl' shared library method", | |
93 dl_load, | |
94 dl_unload, | |
95 dl_bind_var, | |
96 dl_bind_func, | |
97 /* For now, "unbind" doesn't exist */ | |
98 #if 0 | |
99 NULL, /* unbind_var */ | |
100 NULL, /* unbind_func */ | |
101 #endif | |
102 NULL, /* ctrl */ | |
103 dl_name_converter, | |
104 dl_merger, | |
105 NULL, /* init */ | |
106 NULL, /* finish */ | |
107 dl_pathbyaddr, | |
108 dl_globallookup | |
109 }; | |
110 | |
111 DSO_METHOD *DSO_METHOD_dl(void) | |
112 { | |
113 return(&dso_meth_dl); | |
114 } | |
115 | |
116 /* For this DSO_METHOD, our meth_data STACK will contain; | |
117 * (i) the handle (shl_t) returned from shl_load(). | |
118 * NB: I checked on HPUX11 and shl_t is itself a pointer | |
119 * type so the cast is safe. | |
120 */ | |
121 | |
122 static int dl_load(DSO *dso) | |
123 { | |
124 shl_t ptr = NULL; | |
125 /* We don't do any fancy retries or anything, just take the method's | |
126 * (or DSO's if it has the callback set) best translation of the | |
127 * platform-independant filename and try once with that. */ | |
128 char *filename= DSO_convert_filename(dso, NULL); | |
129 | |
130 if(filename == NULL) | |
131 { | |
132 DSOerr(DSO_F_DL_LOAD,DSO_R_NO_FILENAME); | |
133 goto err; | |
134 } | |
135 ptr = shl_load(filename, BIND_IMMEDIATE | | |
136 (dso->flags&DSO_FLAG_NO_NAME_TRANSLATION?0:DYNAMIC_PATH), 0L); | |
137 if(ptr == NULL) | |
138 { | |
139 DSOerr(DSO_F_DL_LOAD,DSO_R_LOAD_FAILED); | |
140 ERR_add_error_data(4, "filename(", filename, "): ", | |
141 strerror(errno)); | |
142 goto err; | |
143 } | |
144 if(!sk_push(dso->meth_data, (char *)ptr)) | |
145 { | |
146 DSOerr(DSO_F_DL_LOAD,DSO_R_STACK_ERROR); | |
147 goto err; | |
148 } | |
149 /* Success, stick the converted filename we've loaded under into the DSO | |
150 * (it also serves as the indicator that we are currently loaded). */ | |
151 dso->loaded_filename = filename; | |
152 return(1); | |
153 err: | |
154 /* Cleanup! */ | |
155 if(filename != NULL) | |
156 OPENSSL_free(filename); | |
157 if(ptr != NULL) | |
158 shl_unload(ptr); | |
159 return(0); | |
160 } | |
161 | |
162 static int dl_unload(DSO *dso) | |
163 { | |
164 shl_t ptr; | |
165 if(dso == NULL) | |
166 { | |
167 DSOerr(DSO_F_DL_UNLOAD,ERR_R_PASSED_NULL_PARAMETER); | |
168 return(0); | |
169 } | |
170 if(sk_num(dso->meth_data) < 1) | |
171 return(1); | |
172 /* Is this statement legal? */ | |
173 ptr = (shl_t)sk_pop(dso->meth_data); | |
174 if(ptr == NULL) | |
175 { | |
176 DSOerr(DSO_F_DL_UNLOAD,DSO_R_NULL_HANDLE); | |
177 /* Should push the value back onto the stack in | |
178 * case of a retry. */ | |
179 sk_push(dso->meth_data, (char *)ptr); | |
180 return(0); | |
181 } | |
182 shl_unload(ptr); | |
183 return(1); | |
184 } | |
185 | |
186 static void *dl_bind_var(DSO *dso, const char *symname) | |
187 { | |
188 shl_t ptr; | |
189 void *sym; | |
190 | |
191 if((dso == NULL) || (symname == NULL)) | |
192 { | |
193 DSOerr(DSO_F_DL_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER); | |
194 return(NULL); | |
195 } | |
196 if(sk_num(dso->meth_data) < 1) | |
197 { | |
198 DSOerr(DSO_F_DL_BIND_VAR,DSO_R_STACK_ERROR); | |
199 return(NULL); | |
200 } | |
201 ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); | |
202 if(ptr == NULL) | |
203 { | |
204 DSOerr(DSO_F_DL_BIND_VAR,DSO_R_NULL_HANDLE); | |
205 return(NULL); | |
206 } | |
207 if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) | |
208 { | |
209 DSOerr(DSO_F_DL_BIND_VAR,DSO_R_SYM_FAILURE); | |
210 ERR_add_error_data(4, "symname(", symname, "): ", | |
211 strerror(errno)); | |
212 return(NULL); | |
213 } | |
214 return(sym); | |
215 } | |
216 | |
217 static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname) | |
218 { | |
219 shl_t ptr; | |
220 void *sym; | |
221 | |
222 if((dso == NULL) || (symname == NULL)) | |
223 { | |
224 DSOerr(DSO_F_DL_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER); | |
225 return(NULL); | |
226 } | |
227 if(sk_num(dso->meth_data) < 1) | |
228 { | |
229 DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_STACK_ERROR); | |
230 return(NULL); | |
231 } | |
232 ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1); | |
233 if(ptr == NULL) | |
234 { | |
235 DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_NULL_HANDLE); | |
236 return(NULL); | |
237 } | |
238 if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) | |
239 { | |
240 DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_SYM_FAILURE); | |
241 ERR_add_error_data(4, "symname(", symname, "): ", | |
242 strerror(errno)); | |
243 return(NULL); | |
244 } | |
245 return((DSO_FUNC_TYPE)sym); | |
246 } | |
247 | |
248 static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2) | |
249 { | |
250 char *merged; | |
251 | |
252 if(!filespec1 && !filespec2) | |
253 { | |
254 DSOerr(DSO_F_DL_MERGER, | |
255 ERR_R_PASSED_NULL_PARAMETER); | |
256 return(NULL); | |
257 } | |
258 /* If the first file specification is a rooted path, it rules. | |
259 same goes if the second file specification is missing. */ | |
260 if (!filespec2 || filespec1[0] == '/') | |
261 { | |
262 merged = OPENSSL_malloc(strlen(filespec1) + 1); | |
263 if(!merged) | |
264 { | |
265 DSOerr(DSO_F_DL_MERGER, | |
266 ERR_R_MALLOC_FAILURE); | |
267 return(NULL); | |
268 } | |
269 strcpy(merged, filespec1); | |
270 } | |
271 /* If the first file specification is missing, the second one rules. */ | |
272 else if (!filespec1) | |
273 { | |
274 merged = OPENSSL_malloc(strlen(filespec2) + 1); | |
275 if(!merged) | |
276 { | |
277 DSOerr(DSO_F_DL_MERGER, | |
278 ERR_R_MALLOC_FAILURE); | |
279 return(NULL); | |
280 } | |
281 strcpy(merged, filespec2); | |
282 } | |
283 else | |
284 /* This part isn't as trivial as it looks. It assumes that | |
285 the second file specification really is a directory, and | |
286 makes no checks whatsoever. Therefore, the result becomes | |
287 the concatenation of filespec2 followed by a slash followed | |
288 by filespec1. */ | |
289 { | |
290 int spec2len, len; | |
291 | |
292 spec2len = (filespec2 ? strlen(filespec2) : 0); | |
293 len = spec2len + (filespec1 ? strlen(filespec1) : 0); | |
294 | |
295 if(filespec2 && filespec2[spec2len - 1] == '/') | |
296 { | |
297 spec2len--; | |
298 len--; | |
299 } | |
300 merged = OPENSSL_malloc(len + 2); | |
301 if(!merged) | |
302 { | |
303 DSOerr(DSO_F_DL_MERGER, | |
304 ERR_R_MALLOC_FAILURE); | |
305 return(NULL); | |
306 } | |
307 strcpy(merged, filespec2); | |
308 merged[spec2len] = '/'; | |
309 strcpy(&merged[spec2len + 1], filespec1); | |
310 } | |
311 return(merged); | |
312 } | |
313 | |
314 /* This function is identical to the one in dso_dlfcn.c, but as it is highly | |
315 * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at the | |
316 * same time, there's no great duplicating the code. Figuring out an elegant | |
317 * way to share one copy of the code would be more difficult and would not | |
318 * leave the implementations independant. */ | |
319 #if defined(__hpux) | |
320 static const char extension[] = ".sl"; | |
321 #else | |
322 static const char extension[] = ".so"; | |
323 #endif | |
324 static char *dl_name_converter(DSO *dso, const char *filename) | |
325 { | |
326 char *translated; | |
327 int len, rsize, transform; | |
328 | |
329 len = strlen(filename); | |
330 rsize = len + 1; | |
331 transform = (strstr(filename, "/") == NULL); | |
332 { | |
333 /* We will convert this to "%s.s?" or "lib%s.s?" */ | |
334 rsize += strlen(extension);/* The length of ".s?" */ | |
335 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) | |
336 rsize += 3; /* The length of "lib" */ | |
337 } | |
338 translated = OPENSSL_malloc(rsize); | |
339 if(translated == NULL) | |
340 { | |
341 DSOerr(DSO_F_DL_NAME_CONVERTER, | |
342 DSO_R_NAME_TRANSLATION_FAILED); | |
343 return(NULL); | |
344 } | |
345 if(transform) | |
346 { | |
347 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0) | |
348 sprintf(translated, "lib%s%s", filename, extension); | |
349 else | |
350 sprintf(translated, "%s%s", filename, extension); | |
351 } | |
352 else | |
353 sprintf(translated, "%s", filename); | |
354 return(translated); | |
355 } | |
356 | |
357 static int dl_pathbyaddr(void *addr,char *path,int sz) | |
358 { | |
359 struct shl_descriptor inf; | |
360 int i,len; | |
361 | |
362 if (addr == NULL) | |
363 { | |
364 union { int(*f)(void*,char*,int); void *p; } t = | |
365 { dl_pathbyaddr }; | |
366 addr = t.p; | |
367 } | |
368 | |
369 for (i=-1;shl_get_r(i,&inf)==0;i++) | |
370 { | |
371 if (((size_t)addr >= inf.tstart && (size_t)addr < inf.tend) || | |
372 ((size_t)addr >= inf.dstart && (size_t)addr < inf.dend)) | |
373 { | |
374 len = (int)strlen(inf.filename); | |
375 if (sz <= 0) return len+1; | |
376 if (len >= sz) len=sz-1; | |
377 memcpy(path,inf.filename,len); | |
378 path[len++] = 0; | |
379 return len; | |
380 } | |
381 } | |
382 | |
383 return -1; | |
384 } | |
385 | |
386 static void *dl_globallookup(const char *name) | |
387 { | |
388 void *ret; | |
389 shl_t h = NULL; | |
390 | |
391 return shl_findsym(&h,name,TYPE_UNDEFINED,&ret) ? NULL : ret; | |
392 } | |
393 #endif /* DSO_DL */ | |
OLD | NEW |