]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/dso/dso_dlfcn.c
Fix probable_prime over large shift
[thirdparty/openssl.git] / crypto / dso / dso_dlfcn.c
CommitLineData
cbecb3ac 1/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */
0f113f3e
MC
2/*
3 * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
4 * 2000.
8f4fac7f
GT
5 */
6/* ====================================================================
7 * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
0f113f3e 14 * notice, this list of conditions and the following disclaimer.
8f4fac7f
GT
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59
0f113f3e
MC
60/*
61 * We need to do this early, because stdio.h includes the header files that
62 * handle _GNU_SOURCE and other similar macros. Defining it later is simply
63 * too late, because those headers are protected from re- inclusion.
64 */
c1844095 65#ifndef _GNU_SOURCE
0f113f3e 66# define _GNU_SOURCE /* make sure dladdr is declared */
3ecbd099
RL
67#endif
68
8f4fac7f
GT
69#include <stdio.h>
70#include "cryptlib.h"
71#include <openssl/dso.h>
72
73#ifndef DSO_DLFCN
74DSO_METHOD *DSO_METHOD_dlfcn(void)
0f113f3e
MC
75{
76 return NULL;
77}
8f4fac7f
GT
78#else
79
0f113f3e
MC
80# ifdef HAVE_DLFCN_H
81# ifdef __osf__
82# define __EXTENSIONS__
83# endif
84# include <dlfcn.h>
85# define HAVE_DLINFO 1
86# if defined(_AIX) || defined(__CYGWIN__) || \
73133962 87 defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
afb41913 88 (defined(__osf__) && !defined(RTLD_NEXT)) || \
7a4ec19a 89 (defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
0f113f3e
MC
90 defined(__ANDROID__)
91# undef HAVE_DLINFO
92# endif
73133962 93# endif
8f4fac7f 94
b9e63915 95/* Part of the hack in "dlfcn_load" ... */
0f113f3e 96# define DSO_MAX_TRANSLATED_SIZE 256
b9e63915 97
51c8dc37 98static int dlfcn_load(DSO *dso);
8f4fac7f 99static int dlfcn_unload(DSO *dso);
e9a68cfb
GT
100static void *dlfcn_bind_var(DSO *dso, const char *symname);
101static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
51c8dc37 102static char *dlfcn_name_converter(DSO *dso, const char *filename);
cbecb3ac 103static char *dlfcn_merger(DSO *dso, const char *filespec1,
0f113f3e
MC
104 const char *filespec2);
105static int dlfcn_pathbyaddr(void *addr, char *path, int sz);
c6cb42e4 106static void *dlfcn_globallookup(const char *name);
8f4fac7f
GT
107
108static DSO_METHOD dso_meth_dlfcn = {
0f113f3e
MC
109 "OpenSSL 'dlfcn' shared library method",
110 dlfcn_load,
111 dlfcn_unload,
112 dlfcn_bind_var,
113 dlfcn_bind_func,
0f113f3e
MC
114 NULL, /* ctrl */
115 dlfcn_name_converter,
116 dlfcn_merger,
117 NULL, /* init */
118 NULL, /* finish */
119 dlfcn_pathbyaddr,
120 dlfcn_globallookup
121};
8f4fac7f
GT
122
123DSO_METHOD *DSO_METHOD_dlfcn(void)
0f113f3e
MC
124{
125 return (&dso_meth_dlfcn);
126}
127
128/*
129 * Prior to using the dlopen() function, we should decide on the flag we
130 * send. There's a few different ways of doing this and it's a messy
131 * venn-diagram to match up which platforms support what. So as we don't have
132 * autoconf yet, I'm implementing a hack that could be hacked further
133 * relatively easily to deal with cases as we find them. Initially this is to
134 * cope with OpenBSD.
135 */
136# if defined(__OpenBSD__) || defined(__NetBSD__)
137# ifdef DL_LAZY
138# define DLOPEN_FLAG DL_LAZY
139# else
140# ifdef RTLD_NOW
141# define DLOPEN_FLAG RTLD_NOW
142# else
143# define DLOPEN_FLAG 0
144# endif
145# endif
146# else
147# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */
148# endif
1a797ac6 149
0f113f3e
MC
150/*
151 * For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
152 * (void*) returned from dlopen().
8f4fac7f
GT
153 */
154
51c8dc37 155static int dlfcn_load(DSO *dso)
0f113f3e
MC
156{
157 void *ptr = NULL;
158 /* See applicable comments in dso_dl.c */
159 char *filename = DSO_convert_filename(dso, NULL);
160 int flags = DLOPEN_FLAG;
161
162 if (filename == NULL) {
163 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
164 goto err;
165 }
166# ifdef RTLD_GLOBAL
167 if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
168 flags |= RTLD_GLOBAL;
169# endif
170 ptr = dlopen(filename, flags);
171 if (ptr == NULL) {
172 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
173 ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
174 goto err;
175 }
176 if (!sk_void_push(dso->meth_data, (char *)ptr)) {
177 DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
178 goto err;
179 }
180 /* Success */
181 dso->loaded_filename = filename;
182 return (1);
183 err:
184 /* Cleanup! */
185 if (filename != NULL)
186 OPENSSL_free(filename);
187 if (ptr != NULL)
188 dlclose(ptr);
189 return (0);
51c8dc37 190}
8f4fac7f
GT
191
192static int dlfcn_unload(DSO *dso)
0f113f3e
MC
193{
194 void *ptr;
195 if (dso == NULL) {
196 DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
197 return (0);
198 }
199 if (sk_void_num(dso->meth_data) < 1)
200 return (1);
201 ptr = sk_void_pop(dso->meth_data);
202 if (ptr == NULL) {
203 DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
204 /*
205 * Should push the value back onto the stack in case of a retry.
206 */
207 sk_void_push(dso->meth_data, ptr);
208 return (0);
209 }
210 /* For now I'm not aware of any errors associated with dlclose() */
211 dlclose(ptr);
212 return (1);
213}
8f4fac7f 214
e9a68cfb 215static void *dlfcn_bind_var(DSO *dso, const char *symname)
0f113f3e
MC
216{
217 void *ptr, *sym;
218
219 if ((dso == NULL) || (symname == NULL)) {
220 DSOerr(DSO_F_DLFCN_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
221 return (NULL);
222 }
223 if (sk_void_num(dso->meth_data) < 1) {
224 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_STACK_ERROR);
225 return (NULL);
226 }
227 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
228 if (ptr == NULL) {
229 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_NULL_HANDLE);
230 return (NULL);
231 }
232 sym = dlsym(ptr, symname);
233 if (sym == NULL) {
234 DSOerr(DSO_F_DLFCN_BIND_VAR, DSO_R_SYM_FAILURE);
235 ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
236 return (NULL);
237 }
238 return (sym);
239}
e9a68cfb
GT
240
241static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
0f113f3e
MC
242{
243 void *ptr;
244 union {
245 DSO_FUNC_TYPE sym;
246 void *dlret;
247 } u;
248
249 if ((dso == NULL) || (symname == NULL)) {
250 DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
251 return (NULL);
252 }
253 if (sk_void_num(dso->meth_data) < 1) {
254 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
255 return (NULL);
256 }
257 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
258 if (ptr == NULL) {
259 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
260 return (NULL);
261 }
262 u.dlret = dlsym(ptr, symname);
263 if (u.dlret == NULL) {
264 DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
265 ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
266 return (NULL);
267 }
268 return u.sym;
269}
8f4fac7f 270
cbecb3ac 271static char *dlfcn_merger(DSO *dso, const char *filespec1,
0f113f3e
MC
272 const char *filespec2)
273{
274 char *merged;
275
276 if (!filespec1 && !filespec2) {
277 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER);
278 return (NULL);
279 }
280 /*
281 * If the first file specification is a rooted path, it rules. same goes
282 * if the second file specification is missing.
283 */
284 if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
285 merged = OPENSSL_malloc(strlen(filespec1) + 1);
286 if (!merged) {
287 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
288 return (NULL);
289 }
290 strcpy(merged, filespec1);
291 }
292 /*
293 * If the first file specification is missing, the second one rules.
294 */
295 else if (!filespec1) {
296 merged = OPENSSL_malloc(strlen(filespec2) + 1);
297 if (!merged) {
298 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
299 return (NULL);
300 }
301 strcpy(merged, filespec2);
302 } else
303 /*
304 * This part isn't as trivial as it looks. It assumes that the
305 * second file specification really is a directory, and makes no
306 * checks whatsoever. Therefore, the result becomes the
307 * concatenation of filespec2 followed by a slash followed by
308 * filespec1.
309 */
310 {
311 int spec2len, len;
312
313 spec2len = strlen(filespec2);
314 len = spec2len + (filespec1 ? strlen(filespec1) : 0);
315
316 if (filespec2 && filespec2[spec2len - 1] == '/') {
317 spec2len--;
318 len--;
319 }
320 merged = OPENSSL_malloc(len + 2);
321 if (!merged) {
322 DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
323 return (NULL);
324 }
325 strcpy(merged, filespec2);
326 merged[spec2len] = '/';
327 strcpy(&merged[spec2len + 1], filespec1);
328 }
329 return (merged);
330}
4a620922 331
0f113f3e
MC
332# ifdef OPENSSL_SYS_MACOSX
333# define DSO_ext ".dylib"
334# define DSO_extlen 6
335# else
336# define DSO_ext ".so"
337# define DSO_extlen 3
338# endif
4a620922 339
51c8dc37 340static char *dlfcn_name_converter(DSO *dso, const char *filename)
0f113f3e
MC
341{
342 char *translated;
343 int len, rsize, transform;
344
345 len = strlen(filename);
346 rsize = len + 1;
347 transform = (strstr(filename, "/") == NULL);
348 if (transform) {
349 /* We will convert this to "%s.so" or "lib%s.so" etc */
350 rsize += DSO_extlen; /* The length of ".so" */
351 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
352 rsize += 3; /* The length of "lib" */
353 }
354 translated = OPENSSL_malloc(rsize);
355 if (translated == NULL) {
356 DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
357 return (NULL);
358 }
359 if (transform) {
360 if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
361 sprintf(translated, "lib%s" DSO_ext, filename);
362 else
363 sprintf(translated, "%s" DSO_ext, filename);
364 } else
365 sprintf(translated, "%s", filename);
366 return (translated);
367}
368
369# ifdef __sgi
23a22b4c 370/*-
7ed87653
AP
371This is a quote from IRIX manual for dladdr(3c):
372
373 <dlfcn.h> does not contain a prototype for dladdr or definition of
374 Dl_info. The #include <dlfcn.h> in the SYNOPSIS line is traditional,
375 but contains no dladdr prototype and no IRIX library contains an
376 implementation. Write your own declaration based on the code below.
377
378 The following code is dependent on internal interfaces that are not
379 part of the IRIX compatibility guarantee; however, there is no future
380 intention to change this interface, so on a practical level, the code
381 below is safe to use on IRIX.
c8e1edaa 382*/
0f113f3e
MC
383# include <rld_interface.h>
384# ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
385# define _RLD_INTERFACE_DLFCN_H_DLADDR
7ed87653 386typedef struct Dl_info {
0f113f3e
MC
387 const char *dli_fname;
388 void *dli_fbase;
389 const char *dli_sname;
390 void *dli_saddr;
391 int dli_version;
392 int dli_reserved1;
393 long dli_reserved[4];
7ed87653 394} Dl_info;
0f113f3e 395# else
7ed87653 396typedef struct Dl_info Dl_info;
0f113f3e
MC
397# endif
398# define _RLD_DLADDR 14
7ed87653
AP
399
400static int dladdr(void *address, Dl_info *dl)
401{
0f113f3e
MC
402 void *v;
403 v = _rld_new_interface(_RLD_DLADDR, address, dl);
404 return (int)v;
405}
406# endif /* __sgi */
407
408static int dlfcn_pathbyaddr(void *addr, char *path, int sz)
409{
410# ifdef HAVE_DLINFO
411 Dl_info dli;
412 int len;
413
414 if (addr == NULL) {
415 union {
416 int (*f) (void *, char *, int);
417 void *p;
418 } t = {
419 dlfcn_pathbyaddr
420 };
421 addr = t.p;
422 }
423
424 if (dladdr(addr, &dli)) {
425 len = (int)strlen(dli.dli_fname);
426 if (sz <= 0)
427 return len + 1;
428 if (len >= sz)
429 len = sz - 1;
430 memcpy(path, dli.dli_fname, len);
431 path[len++] = 0;
432 return len;
433 }
434
435 ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror());
436# endif
437 return -1;
7ed87653 438}
68b64fb6 439
c6cb42e4 440static void *dlfcn_globallookup(const char *name)
0f113f3e
MC
441{
442 void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
443
444 if (handle) {
445 ret = dlsym(handle, name);
446 dlclose(handle);
447 }
448
449 return ret;
450}
451#endif /* DSO_DLFCN */