summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/dso/dso_dlfcn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/dso/dso_dlfcn.c')
-rw-r--r--src/lib/libcrypto/dso/dso_dlfcn.c355
1 files changed, 0 insertions, 355 deletions
diff --git a/src/lib/libcrypto/dso/dso_dlfcn.c b/src/lib/libcrypto/dso/dso_dlfcn.c
deleted file mode 100644
index f22e641bab..0000000000
--- a/src/lib/libcrypto/dso/dso_dlfcn.c
+++ /dev/null
@@ -1,355 +0,0 @@
1/* $OpenBSD: dso_dlfcn.c,v 1.28 2015/02/07 13:19:15 doug Exp $ */
2/* Written by Geoff Thorpe (geoff@geoffthorpe.net) 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 <string.h>
61
62#include <openssl/dso.h>
63#include <openssl/err.h>
64
65#ifndef DSO_DLFCN
66DSO_METHOD *
67DSO_METHOD_dlfcn(void)
68{
69 return NULL;
70}
71#else
72
73#ifdef HAVE_DLFCN_H
74# include <dlfcn.h>
75# define HAVE_DLINFO 1
76#endif
77
78/* Part of the hack in "dlfcn_load" ... */
79#define DSO_MAX_TRANSLATED_SIZE 256
80
81static int dlfcn_load(DSO *dso);
82static int dlfcn_unload(DSO *dso);
83static void *dlfcn_bind_var(DSO *dso, const char *symname);
84static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
85static char *dlfcn_name_converter(DSO *dso, const char *filename);
86static char *dlfcn_merger(DSO *dso, const char *filespec1,
87 const char *filespec2);
88static int dlfcn_pathbyaddr(void *addr, char *path, int sz);
89static void *dlfcn_globallookup(const char *name);
90
91static DSO_METHOD dso_meth_dlfcn = {
92 .name = "OpenSSL 'dlfcn' shared library method",
93 .dso_load = dlfcn_load,
94 .dso_unload = dlfcn_unload,
95 .dso_bind_var = dlfcn_bind_var,
96 .dso_bind_func = dlfcn_bind_func,
97 .dso_name_converter = dlfcn_name_converter,
98 .dso_merger = dlfcn_merger,
99 .pathbyaddr = dlfcn_pathbyaddr,
100 .globallookup = dlfcn_globallookup
101};
102
103DSO_METHOD *
104DSO_METHOD_dlfcn(void)
105{
106 return (&dso_meth_dlfcn);
107}
108
109/* For this DSO_METHOD, our meth_data STACK will contain;
110 * (i) the handle (void*) returned from dlopen().
111 */
112
113static int
114dlfcn_load(DSO *dso)
115{
116 void *ptr = NULL;
117 /* See applicable comments in dso_dl.c */
118 char *filename = DSO_convert_filename(dso, NULL);
119 int flags = RTLD_LAZY;
120
121 if (filename == NULL) {
122 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
123 goto err;
124 }
125
126 if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
127 flags |= RTLD_GLOBAL;
128 ptr = dlopen(filename, flags);
129 if (ptr == NULL) {
130 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
131 ERR_asprintf_error_data("filename(%s): %s", filename,
132 dlerror());
133 goto err;
134 }
135 if (!sk_void_push(dso->meth_data, (char *)ptr)) {
136 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
137 goto err;
138 }
139 /* Success */
140 dso->loaded_filename = filename;
141 return (1);
142
143err:
144 /* Cleanup! */
145 free(filename);
146 if (ptr != NULL)
147 dlclose(ptr);
148 return (0);
149}
150
151static int
152dlfcn_unload(DSO *dso)
153{
154 void *ptr;
155 if (dso == NULL) {
156 DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
157 return (0);
158 }
159 if (sk_void_num(dso->meth_data) < 1)
160 return (1);
161 ptr = sk_void_pop(dso->meth_data);
162 if (ptr == NULL) {
163 DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
164 /* Should push the value back onto the stack in
165 * case of a retry. */
166 sk_void_push(dso->meth_data, ptr);
167 return (0);
168 }
169 /* For now I'm not aware of any errors associated with dlclose() */
170 dlclose(ptr);
171 return (1);
172}
173
174static void *
175dlfcn_bind_var(DSO *dso, const char *symname)
176{
177 void *ptr, *sym;
178
179 if ((dso == NULL) || (symname == NULL)) {
180 DSOerr(DSO_F_DLFCN_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
181 return (NULL);
182 }
183 if (sk_void_num(dso->meth_data) < 1) {
184 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_STACK_ERROR);
185 return (NULL);
186 }
187 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
188 if (ptr == NULL) {
189 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_NULL_HANDLE);
190 return (NULL);
191 }
192 sym = dlsym(ptr, symname);
193 if (sym == NULL) {
194 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_SYM_FAILURE);
195 ERR_asprintf_error_data("symname(%s): %s", symname, dlerror());
196 return (NULL);
197 }
198 return (sym);
199}
200
201static DSO_FUNC_TYPE
202dlfcn_bind_func(DSO *dso, const char *symname)
203{
204 void *ptr;
205 union {
206 DSO_FUNC_TYPE sym;
207 void *dlret;
208 } u;
209
210 if ((dso == NULL) || (symname == NULL)) {
211 DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
212 return (NULL);
213 }
214 if (sk_void_num(dso->meth_data) < 1) {
215 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
216 return (NULL);
217 }
218 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
219 if (ptr == NULL) {
220 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
221 return (NULL);
222 }
223 u.dlret = dlsym(ptr, symname);
224 if (u.dlret == NULL) {
225 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
226 ERR_asprintf_error_data("symname(%s): %s", symname, dlerror());
227 return (NULL);
228 }
229 return u.sym;
230}
231
232static char *
233dlfcn_merger(DSO *dso, const char *filespec1, const char *filespec2)
234{
235 char *merged;
236
237 if (!filespec1 && !filespec2) {
238 DSOerr(DSO_F_DLFCN_MERGER,
239 ERR_R_PASSED_NULL_PARAMETER);
240 return (NULL);
241 }
242 /* If the first file specification is a rooted path, it rules.
243 same goes if the second file specification is missing. */
244 if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
245 merged = strdup(filespec1);
246 if (!merged) {
247 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
248 return (NULL);
249 }
250 }
251 /* If the first file specification is missing, the second one rules. */
252 else if (!filespec1) {
253 merged = strdup(filespec2);
254 if (!merged) {
255 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
256 return (NULL);
257 }
258 } else
259 /* This part isn't as trivial as it looks. It assumes that
260 the second file specification really is a directory, and
261 makes no checks whatsoever. Therefore, the result becomes
262 the concatenation of filespec2 followed by a slash followed
263 by filespec1. */
264 {
265 size_t spec2len, len;
266
267 spec2len = strlen(filespec2);
268 len = spec2len + (filespec1 ? strlen(filespec1) : 0);
269
270 if (filespec2 && filespec2[spec2len - 1] == '/') {
271 spec2len--;
272 len--;
273 }
274 merged = malloc(len + 2);
275 if (!merged) {
276 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
277 return (NULL);
278 }
279 strlcpy(merged, filespec2, len + 2);
280 merged[spec2len] = '/';
281 strlcpy(&merged[spec2len + 1], filespec1, len + 1 - spec2len);
282 }
283 return (merged);
284}
285
286#define DSO_ext ".so"
287#define DSO_extlen 3
288
289static char *
290dlfcn_name_converter(DSO *dso, const char *filename)
291{
292 char *translated;
293 int ret;
294
295 if (strchr(filename, '/') == NULL) {
296 /* Bare name, so convert to "%s.so" or "lib%s.so" */
297 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
298 ret = asprintf(&translated, "lib%s" DSO_ext, filename);
299 else
300 ret = asprintf(&translated, "%s" DSO_ext, filename);
301 if (ret == -1)
302 translated = NULL;
303 } else {
304 /* Full path, so just duplicate it */
305 translated = strdup(filename);
306 }
307
308 if (translated == NULL)
309 DSOerr(DSO_F_DLFCN_NAME_CONVERTER,
310 DSO_R_NAME_TRANSLATION_FAILED);
311 return (translated);
312}
313
314static int
315dlfcn_pathbyaddr(void *addr, char *path, int sz)
316{
317 Dl_info dli;
318 int len;
319
320 if (addr == NULL) {
321 union{
322 int(*f)(void*, char*, int);
323 void *p;
324 } t = { dlfcn_pathbyaddr };
325 addr = t.p;
326 }
327
328 if (dladdr(addr, &dli)) {
329 len = (int)strlen(dli.dli_fname);
330 if (sz <= 0)
331 return len + 1;
332 if (len >= sz)
333 len = sz - 1;
334 memcpy(path, dli.dli_fname, len);
335 path[len++] = 0;
336 return len;
337 }
338
339 ERR_asprintf_error_data("dlfcn_pathbyaddr(): %s", dlerror());
340 return -1;
341}
342
343static void *
344dlfcn_globallookup(const char *name)
345{
346 void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
347
348 if (handle) {
349 ret = dlsym(handle, name);
350 dlclose(handle);
351 }
352
353 return ret;
354}
355#endif /* DSO_DLFCN */