| 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 |