OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
dso_dl.c
Go to the documentation of this file.
1 /* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte ([email protected]) 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
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  * ([email protected]). This product includes software written by Tim
55  * Hudson ([email protected]).
56  *
57  */
58 
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/dso.h>
62 
63 #ifndef DSO_DL
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 
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  {
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  {
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  {
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  {
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  {
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  {
194  return(NULL);
195  }
196  if(sk_num(dso->meth_data) < 1)
197  {
199  return(NULL);
200  }
201  ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
202  if(ptr == NULL)
203  {
205  return(NULL);
206  }
207  if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0)
208  {
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  {
225  return(NULL);
226  }
227  if(sk_num(dso->meth_data) < 1)
228  {
230  return(NULL);
231  }
232  ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
233  if(ptr == NULL)
234  {
236  return(NULL);
237  }
238  if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0)
239  {
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  {
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  {
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  {
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  {
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?" */
336  rsize += 3; /* The length of "lib" */
337  }
338  translated = OPENSSL_malloc(rsize);
339  if(translated == NULL)
340  {
343  return(NULL);
344  }
345  if(transform)
346  {
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 */